WPF: Modifying a ControlTemplate property from a DataTemplate?
Using an MVVM approach to WPF, I have a view model class called SubButton
. It is styled as follows:
<!-- SubNavButton Appearance -->
<ControlTemplate x:Key="SubNavButton" TargetType="{x:Type RadioButton}">
<Grid Margin="5,5">
<Rectangle x:Name="rectBackground" Fill="DimGray" Stroke="#FF000000" Width="150" Height="40" StrokeThickness="1"/>
<TextBlock x:Name="txtContent" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Arial" FontSize="16">
<ContentPresenter />
</TextBlock>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" TargetName="rectBackground" Value="Red"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Fill" TargetName="rectBackground" Value="Pink"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- SubButton data template -->
<DataTemplate DataType="{x:Type VM:SubButton}">
<RadioButton
Template="{StaticResource SubNavButton}"
Content="{Binding TempText}"
Command="{Binding SubFrameChanger.Command}"
CommandParameter="{Binding Key}"
GroupName="{Binding MenuGroup}"
V:CreateCommandBinding.Comm开发者_JAVA技巧and="{Binding SubFrameChanger}" />
<DataTemplate.Triggers>
<!-- This trigger doesn't work -->
<DataTrigger Binding="{Binding Path=Selected}" Value="True">
<Setter TargetName="rectBackground" Property="Fill" Value="Green"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
The DataTrigger
doesn't work. Selected
is a regular .Net property on the SubButton
class. I am getting a compilation error because the compiler can't figure out where the rectBackground
target comes from. It is part of the ControlTemplate
, I'm not sure how to tell it that? Something about the DataContext
?
What you want is not possible. WPF works with NameScopes and the name rectBackground is out of scope in the DataTemplate. The original name rectBackground will only be in scope inside the original ControlTemplate. This is fortunate, because otherwise you would not be able to use a duplicate name throughout your entire application. What you can do is bind the Fill property of rectBackground to the RadioButton's Background property through TemplateBinding. When you change the RadioButton's Background anywhere else in your code rectBackground will get this Brush as its Fill. I modified your code somewhat to illustrate the point. It will be easy to change this to your model with a DataTemplate.
<Window.Resources>
<ControlTemplate x:Key="SubNavButton" TargetType="RadioButton">
<Grid Margin="5,5">
<Rectangle x:Name="rectBackground"
Fill="{TemplateBinding Background}"
Stroke="#FF000000" Width="150" Height="40"
StrokeThickness="1"/>
<TextBlock x:Name="txtContent" HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="Arial" FontSize="16">
<ContentPresenter />
</TextBlock>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill"
TargetName="rectBackground" Value="Red"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Fill"
TargetName="rectBackground" Value="Pink"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- The Style simulates the same behavior as the DataTemplate-->
<Style TargetType="RadioButton">
<Setter Property="Template"
Value="{StaticResource SubNavButton}"/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<RadioButton>one</RadioButton>
<RadioButton>two</RadioButton>
</StackPanel>
精彩评论