Reputation: 2830
I have a View OutputOptionsView
which holds several UserControls
with options settings which are displayed depending on the selection of a combobox.
I create the Datacontext
and Datatemplates
for the UserControls
within OutputOptionsView
like this:
<UserControl.Resources>
<ResourceDictionary>
<local:OutputOptionsViewModel x:Key="vm" />
<DataTemplate x:Key="OptionSettings1" DataType="{x:Type views:OptionSettings1View}">
<views:OptionSettings1View />
</DataTemplate>
<DataTemplate x:Key="OptionSettings2" DataType="{x:Type views:OptionSettings2View}">
<views:OptionSettings2View />
</DataTemplate>
....
</ResourceDictionary>
</UserControl.Resources>
The display of the OptionSettingsViews
is handled as follows:
<ContentControl Name="OutputOptionsContentControl" Content="{Binding}" >
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource OptionSettings1}" />
<Style.Triggers>
<DataTrigger Binding="{Binding AvailableOptionsListSelectedIndex}" Value="1">
<Setter Property="ContentTemplate" Value="{StaticResource OptionSettings2}" />
</DataTrigger>
...
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
ItemsSource
and SelectedIndex
of the ComboBox are bound to the viewmodel class OutputOptionsViewModel
of the OutputOptionsView
:
<ComboBox Name="AvailableOptionsListComboBox" ItemsSource="{Binding AvailableOptionsList}" DisplayMemberPath="OptionTitle"
SelectedIndex="{Binding AvailableOptionsListSelectedIndex, UpdateSourceTrigger=PropertyChanged}"/>
Each of my OptionSettings
view also gets a ViewModel:
<UserControl.Resources>
<ResourceDictionary>
<local:OptionSettings1ViewModel x:Key="vm" />
</ResourceDictionary>
</UserControl.Resources>
<Grid DataContext="{StaticResource vm}">
...
</Grid>
Now my Issue concerns the population of the population of the combobox. I created an Interface containing the OptionTitle which each OptionsSettingsViewModels
inherits. AvailableOptionsList
which is the ItemsSouce
for the combobox is a List of this Interface.
public List<IOutputOption> AvailableOptionsList { get; set; }
It will be instantiated within the Constructor of the OutputOptionsViewModel
class.
Within each of the OptionSettingsViewModel
class constructors I add the respective OptionsSettingsViewModel
to this List:
public OptionSettings1ViewModel()
{
OutputOptionsViewModel.AvailableOptionsList.Add(this);
}
This leads to the following Problem: The combobox isn't populated as long as the OptionSettingsViews aren't instantiated, but they can't be instantiated , because they can't be selected from the empty combobox. Therefore I'm looking to force the Instantiation of the OptionSettingsViews.
Upvotes: 0
Views: 428
Reputation: 13438
The comments made me think, there is some basic misunderstanding:
[Lynn Crumbling] I'd completely re-architect this to always instantiate all of the viewmodels, nesting them under the mainviewmodel. You're going to need them, so why not just spin them up in the ctor of the main vm?
and
[Roland Deschain] that is actually how I solved it at the moment, however this means that I have to set the datacontext in the code-behind of each optionssettingsviewmodel, which was what I wanted to avoid if possible
So, as Lynn said, you should start by registering the sub-viewmodels within the main viewmodel, no need for any view involvement at this point.
Then you can define DataTemplate
for the viewmodels, not for the views as you do now.
<DataTemplate DataType="{x:Type viewmodels:OptionSettings1ViewModel}">
<views:OptionSettings1View />
</DataTemplate>
<DataTemplate DataType="{x:Type viewmodels:OptionSettings2ViewModel}">
<views:OptionSettings2View />
</DataTemplate>
By removing the x:Key
and changing the DataType
to the viewmodel type, the templates will be automatically selected to display content of the respective type.
The DataContext of your sub-views will be automatically set from the outside. Do not instantiate a sub-viewmodel within the controls xaml.
In your main OutputOptionsViewModel
, you should host a collection of the sub-viewmodels. In your combobox, you should directly use this collection as itemssource.
Then just drop all the complicated template selection xaml and directly bind the content to your selected sub-viewmodel:
<ContentControl
Name="OutputOptionsContentControl"
Content="{Binding ElementName=AvailableOptionsListComboBox,Path=SelectedItem}" />
Upvotes: 1