In a C# WPF project, I have a ContentControl
in the MainWindow
. I bind to the whole MainViewModel
which is my DataContext
. Only bind on my StreamDeckViewModel
StreamDeck
didn’t work.
My DataTemplateSelector
is just hit once, but not when I change the value of the InputMode
in my KeyViewModel
. The KeyViewModel
is in the StreamDeckViewModel
which is in the MainViewModel
. I use the NuGet CommunityToolkit.mvvm, all my view models inherit from ObservableObject
and I use Full-Properties with their backing fields.
Markup in my MainWindow.xaml
:
<ContentControl Content="{Binding}"
ContentTemplateSelector="{StaticResource FromModeTemplateSelector}" />
<Window.Resources>
<DataTemplate x:Key="OpeningModeTemplate">
<ScrollViewer>
<DockPanel VerticalAlignment="Top">
<ComboBox
DockPanel.Dock="Top"
ItemsSource="{Binding StreamDeck.SelectedKey.ActionChoices}"
SelectedIndex="{Binding StreamDeck.SelectedKey.SelectedActionIndex}" />
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label Content="{x:Static resx:Resources.ChooseFilePath}" />
<Button
Width="30"
Background="Transparent"
BorderBrush="Transparent"
Command="{Binding SelectFileToOpenCommand}"
DockPanel.Dock="Right">
<Image Source="/EmbeddedResourcesIn/file.png" />
</Button>
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label Content="{x:Static resx:Resources.ChooseFolderPath}" />
<Button
Width="30"
Background="Transparent"
BorderBrush="Transparent"
Command="{Binding SelectFolderToOpenCommand}"
DockPanel.Dock="Right">
<Image Source="/EmbeddedResourcesIn/folder.png" />
</Button>
</StackPanel>
<ScrollViewer
DockPanel.Dock="Top"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Disabled">
<TextBlock Text="{Binding StreamDeck.SelectedKey.Path}" />
</ScrollViewer>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label Content="{x:Static resx:Resources.ActualizeImage}" />
<CheckBox IsChecked="{Binding Path=StreamDeck.SelectedKey.ActualizeImage, Mode=TwoWay}" />
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label Content="{x:Static resx:Resources.ChooseImagePath}" />
<Button
Width="30"
Background="Transparent"
BorderBrush="Transparent"
Command="{Binding SelectImagePathCommand}"
DockPanel.Dock="Right">
<Image Source="/EmbeddedResourcesIn/image.png" />
</Button>
</StackPanel>
<ScrollViewer
DockPanel.Dock="Top"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Disabled">
<TextBlock Text="{Binding StreamDeck.SelectedKey.ImagePath}" />
</ScrollViewer>
<Label Content="{x:Static resx:Resources.TypeText}" DockPanel.Dock="Top" />
<TextBox DockPanel.Dock="Top" Text="{Binding StreamDeck.SelectedKey.Text.Content}" />
<Label Content="{x:Static resx:Resources.ChooseTextColor}" DockPanel.Dock="Top" />
<ComboBox
DockPanel.Dock="Top"
ItemsSource="{Binding StreamDeck.SelectedKey.Text.ColorChoices}"
SelectedIndex="{Binding StreamDeck.SelectedKey.Text.SelectedColorIndex}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle
Width="10"
Height="10"
Fill="{Binding Code}" />
<TextBlock
Margin="5"
VerticalAlignment="Center"
Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DockPanel>
</ScrollViewer>
</DataTemplate>
<DataTemplate x:Key="ShortcutModeTemplate">
<ScrollViewer>
<DockPanel VerticalAlignment="Top">
<ComboBox
DockPanel.Dock="Top"
ItemsSource="{Binding StreamDeck.SelectedKey.ActionChoices}"
SelectedIndex="{Binding StreamDeck.SelectedKey.SelectedActionIndex}" />
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label Content="{x:Static resx:Resources.EnterShortcut}" />
<Button
Width="30"
Background="Transparent"
BorderBrush="Transparent"
Command="{Binding EnterShortcutCommand}"
DockPanel.Dock="Right">
<Image Source="/EmbeddedResourcesIn/shortcutMiniBlack.png" />
</Button>
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label Content="{x:Static resx:Resources.ActualizeImage}" />
<CheckBox IsChecked="{Binding Path=StreamDeck.SelectedKey.ActualizeImage, Mode=TwoWay}" />
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label Content="{x:Static resx:Resources.ChooseImagePath}" />
<Button
Width="30"
Background="Transparent"
BorderBrush="Transparent"
Command="{Binding SelectImagePathCommand}"
DockPanel.Dock="Right">
<Image Source="/EmbeddedResourcesIn/image.png" />
</Button>
</StackPanel>
<ScrollViewer
DockPanel.Dock="Top"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Disabled">
<TextBlock Text="{Binding StreamDeck.SelectedKey.ImagePath}" />
</ScrollViewer>
<Label Content="{x:Static resx:Resources.TypeText}" DockPanel.Dock="Top" />
<TextBox DockPanel.Dock="Top" Text="{Binding StreamDeck.SelectedKey.Text.Content}" />
<Label Content="{x:Static resx:Resources.ChooseTextColor}" DockPanel.Dock="Top" />
<ComboBox
DockPanel.Dock="Top"
ItemsSource="{Binding StreamDeck.SelectedKey.Text.ColorChoices}"
SelectedIndex="{Binding StreamDeck.SelectedKey.Text.SelectedColorIndex}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle
Width="10"
Height="10"
Fill="{Binding Code}" />
<TextBlock
Margin="5"
VerticalAlignment="Center"
Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DockPanel>
</ScrollViewer>
</DataTemplate>
<dts:FromModeTemplateSelector
x:Key="FromModeTemplateSelector"
OpeningModeTemplate="{StaticResource OpeningModeTemplate}"
ShortcutModeTemplate="{StaticResource ShortcutModeTemplate}" />
</Window.Resources>
Code in my KeyViewModel
:
public InputModeBase InputMode { get => inputMode; set => SetProperty(ref inputMode, value); }
private InputModeBase inputMode = new OpeningMode();
public int SelectedActionIndex
{
get => selectedActionIndex;
set
{
SetProperty(ref selectedActionIndex, value);
if (selectedActionIndex == Constants.OPEN_INDEX)
{
InputMode = new OpeningMode();
}
else if (selectedActionIndex == Constants.SHORTCUT_INDEX)
{
InputMode = new ShortcutMode();
}
}
}
private int selectedActionIndex = 0;
My DataTemplateSelector
:
public class FromModeTemplateSelector : DataTemplateSelector
{
public System.Windows.DataTemplate OpeningModeTemplate { get; set; } = new();
public System.Windows.DataTemplate ShortcutModeTemplate { get; set; } = new();
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
{
if (container is System.Windows.FrameworkElement && item != null && item is MainViewModel mainViewModel)
{
if (mainViewModel.StreamDeck.SelectedKey.InputMode is OpeningMode)
{
return OpeningModeTemplate;
}
else if (mainViewModel.StreamDeck.SelectedKey.InputMode is ShortcutMode)
{
return ShortcutModeTemplate;
}
}
return base.SelectTemplate(item, container);
}
}
Philipp Feldmann FV Feldmann is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.