I have a WPF application using MVVM Light.
One MainView (+ MainViewModel) and One User Control (+ UCViewModel).
The application will have a Tab control with 2 Tab Items.
Each tab will have a user control (same user control).
User Control job: Load the contents of the file, display the contents (and allow user to export it out to other format).
When application launch, I will read a config file and will pass the file location (from config file) to each user control (Eg: File1Path, File2Path).
I can use MVVM Light Messenger.Default.Send
to do this job (From MainViewModel to UCViewModel).
My issue is: How can I differentiate which User Control will get which file path?
I use SimpleIoc.Default.Register
in ViewModelLocator
to register my MainViewModel and UCViewModel.
At the time of registration, I do not have the data from Config file yet so I cannot pass it to UCViewModel.
Any comment/solution for my issue?
Method 1 (by using mm8's way)
As per @mm8 suggested, I ends up declaring DataContext for each UserControl usage in my MainViewModel class as Properties.
Example (in MainView xaml):
<v:UC Grid.Row="0" HorizontalAlignment="Stretch" Margin="10" DataContext="{Binding UC2DC}" />
However, in order for me to support my design time XAML intelliense supports, I still use default MVVM Light way of DataContext binding.
Example: In ViewModelLocator,
static ViewModelLocator()
{
....
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<UCViewModel>();
....
}
public UCViewModel CM
{
get
{
return ServiceLocator.Current.GetInstance<UCViewModel>();
}
}
And in MainViewModel,
private UCViewModel _uC2DC;
public UCViewModel UC2DC
{
get { return _uC2DC; }
set { Set(ref _uC2DC, value); }
}
private UCViewModel _uC1DC;
public UCViewModel UC1DC
{
get { return _uC1DC; }
set { Set(ref _uC1DC, value); }
}
And somewhere in my MainViewModel, I need to create new instances and put into these properties.
When I finish everything, I will delete/comment out User Control default MVVM Light DataContext binding, ViewModelLocator's SimpleIoc Register and GetInstance property,etc and it will change to my MainView databinding.
I am not so sure does it Ok with MVVM way but as of now, it solves my issue.
Method 2 (by using Marco's way)
After Marco sample code, I came to know that we can register multiple instances of ViewModel with a key to differentiate them and when calling in property, use that key to pull the correct one.
Below is the code...
For ViewModelLocator
static ViewModelLocator()
{
...
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register(() => new UCViewModel(), "1");
SimpleIoc.Default.Register(() => new UCViewModel(), "2");
...
}
public UCViewModel UCVM1
{
get
{
return ServiceLocator.Current.GetInstance<UCViewModel>("1");
}
}
public UCViewModel UCVM2
{
get
{
return ServiceLocator.Current.GetInstance<UCViewModel>("2");
}
}
And in my MainView XAML
<TabControl>
<TabItem Header="Test 1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="70"/>
<RowDefinition Height="70"/>
</Grid.RowDefinitions>
<v:UC Grid.Row="0" HorizontalAlignment="Stretch" Margin="10"
DataContext="{Binding UCVM1,Source={StaticResource Locator}}" />
...
...
</Grid>
</TabItem>
<TabItem Header="Test 2">
<Grid Background="AliceBlue">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="70"/>
<RowDefinition Height="70"/>
</Grid.RowDefinitions>
<v:UC Grid.Row="0" HorizontalAlignment="Stretch" Margin="10"
DataContext="{Binding UCVM2,Source={StaticResource Locator}}" />
...
...
</Grid>
</TabItem>
</TabControl>
For this approach, it still the same, for design time, we cannot bind to one default DataContext. May be this is give and take for such cases.