Introduction
I had the requirement to change an icon dependent on the state. I would normally do this by controlling the visibility of each image, but thought that there might be a better way. This tip presents a way to do this using a ContentContol
and Binding
.
The Sample
Here is the XAML for the Window
that uses this technique:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="400"
Height="300"
mc:Ignorable="d">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<Window.Resources>
<ContentControl x:Key="RedXControl">
<Viewbox>
<Border Width="40"
Height="40"
Background="#FFCE1319"
CornerRadius="20">
<Viewbox Width="24"
Height="24"
HorizontalAlignment="center"
VerticalAlignment="Center"
Stretch="Uniform">
<Path Margin="-15.79,-30,0,-20"
Data="F1 M 0380.52, 0014.92L 0273.68, 0185.42L 0397.49, 0382.49L 0266.19, 0382.49L
0198.323, 0266.74L 0129.807, 0382.49L 0026.551, 0382.49L 0144.956, 0192.7L 0031.399,
0014.92L 0163.002, 0014.92L 0220.03, 0113.84L 0279.22, 0014.92L 0380.52, 0014.92 Z"
Fill="White" />
</Viewbox>
</Border>
</Viewbox>
</ContentControl>
<ContentControl x:Key="GreenCheckControl">
<Viewbox>
<Border Width="40"
Height="40"
Background="#FF458E1D"
CornerRadius="20">
<Viewbox Width="24"
Height="24"
HorizontalAlignment="center"
VerticalAlignment="Center"
Stretch="Uniform">
<Path Margin="-25.79,-90,0,0"
Data="F1 M 25.79, 0322.56C 0025.79, 0322.56 0074.77, 0331.72 0118.85, 0472.12L 0164.56,
0440.08C 0164.56, 0440.08 0215.17, 0263.05 0442.09, 0110.44L 0432.3, 0092.12C 0432.3,
0092.12 0213.54, 0218.79 0136.8, 0380.56C 0136.8, 0380.56 0110.68, 0304.25 0069.87,
0298.15C 0069.87, 0298.15 015.87, 0317.99 0025.79, 0322.56 Z "
Fill="White" />
</Viewbox>
</Border>
</Viewbox>
</ContentControl>
<ContentControl x:Key="BlueQuestionControl">
<Viewbox>
<Border Width="40"
Height="40"
Background="#FF458E1D"
CornerRadius="20">
<Viewbox Width="50"
Height="24"
HorizontalAlignment="center"
VerticalAlignment="Center"
Stretch="Uniform">
<Path Margin="-25.79,-90,0,0"
Data="F1 M 0217.2, 0472.65L 0114.06, 0472.65L 0114.06, 0374.36L 0217.2, 0374.36M
0117.57, 0236.49L 0018.74, 0225.72C 0033.82, 0141.52 0082.74, 0099.42 0165.5,
0099.42C 0207.14, 0099.42 0240, 0110.42 0264.06, 0132.41C 0288.11, 0154.4 300.14,
0181.65 0300.14, 0214.14C 0300.14, 0228.5 0297.76, 0241.6 0293, 0253.45C 0288.24,
0265.3 0282.14, 0275.04 0274.69, 0282.67C 0267.24, 0290.3 0255.17, 0300.22 0238.47,
0312.42C 0225.72, 0321.76 0217.61, 0328.54 0214.1, 0332.75C 0210.6, 0336.98 0208.22,
0343.12 0206.97, 0351.2L 0117.57, 0351.2C 0117.57, 0329.48 0119.49, 0313.82 0123.36,
0304.21C 0127.22, 0294.61 0135.16, 0284.42 0147.19, 0273.65C 0165.32, 0257.32
0176.63, 0245.15 0181.12, 0237.16C 0185.6, 0229.18 0187.85, 0219.88 0187.85,
0209.29C 0187.85, 0198.16 0184.89, 0189.59 0178.96, 0183.57C 0173.04,
0177.56 0165.68, 0174.55 0156.88, 0174.55C 0130.85, 0174.55 0117.74,
0195.2 0117.57, 0236.49 Z "
Fill="White" />
</Viewbox>
</Border>
</Viewbox>
</ContentControl>
<DataTemplate DataType="{x:Type local:ShowCheck}">
<ContentControl Content="{StaticResource GreenCheckControl}" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ShowQueston}">
<ContentControl Content="{StaticResource BlueQuestionControl}" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ShowX}">
<ContentControl Content="{StaticResource RedXControl}" />
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Vertical">
<RadioButton Content="Question Selected"
IsChecked="{Binding QuestionChecked}" />
<RadioButton Content="Check Selected"
IsChecked="{Binding CheckChecked}" />
<RadioButton Content="X Selected"
IsChecked="{Binding XChecked}" />
</StackPanel>
<ContentControl Grid.Column="1"
Margin="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding Icon}" />
</Grid>
</Window>
The important parts are that a DataTemplate
is exits containing the XAML for each image that is to be displayed, and that DataTemplate
is associated with a ViewModel
. A ContentControl
is placed at the location where the images are to appear, and the Content
for that ContentControl
is bound to a property in the ViewModel
that is set to an instance of the class
that is associated with the image in the DataTemplate
.
Conclusion
Don’t know why I did not think of this earlier. It does make things very simple and clear, and I have used the DataTemplate
associated with a class
and ContentControl
a lot in the work I have done. A lot easier than trying to do this with Visibility
either through a converter or directly.
History
- 03/03/2018: Initial version