我创建了ControlTemplates
:
<Window.Resources>
<ControlTemplate x:Key="imgNo" TargetType="{x:Type Control}">
<Image Source="pack://application:,,,/Images/up.png"/>
</ControlTemplate>
<ControlTemplate x:Key="imgUp" TargetType="{x:Type Control}">
<!--<TextBlock Text="Up"/>-->
<Image Source="pack://application:,,,/Images/up.png"/>
</ControlTemplate>
<ControlTemplate x:Key="imgDown" TargetType="{x:Type Control}">
<Image Source="pack://application:,,,/Images/downArrow.png"/>
</ControlTemplate>
<DataTemplate x:Key="ButtonOneDataTemplate">
<Control x:Name="theControl" Template="{DynamicResource imgNo}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsImageChanged}" Value="true">
<Setter TargetName="theControl" Property="Template" Value="{DynamicResource imgUp}" />
</DataTrigger>
<DataTrigger Binding="{Binding IsImageChanged}" Value="false">
<Setter TargetName="theControl" Property="Template" Value="{DynamicResource imgDown}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</WindowResources>
使用上述Button
:的DataGrid
中的和ControlTemplates
<DataGrid ItemsSource="{Binding Persons}" Grid.Row="1" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding IdPerson}">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<Border Background="Violet">
<StackPanel>
<Button ContentTemplate="{StaticResource ButtonOneDataTemplate}"
Command="{Binding DataContext.HelloCommand, RelativeSource=
{RelativeSource AncestorType=Window}}"
CommandParameter="{Binding DataContext.Hello,
RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
</StackPanel>
</Border>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
我的ViewModel
:
public class MainWindowViewModel:ViewModelBase
{
public RelayCommand HelloCommand { get; set; }
public MainWindowViewModel()
{
LoadPersons();
HelloCommand = new RelayCommand(SayHello);
}
int helloCounter = 0;
private void SayHello(object obj)
{
if (helloCounter % 2 == 0)
IsImageChanged = true;
else
IsImageChanged = false;
helloCounter++;
}
private bool isImageChanged=true;
public bool IsImageChanged
{
get { return isImageChanged; }
set { isImageChanged = value;
OnPropertyChanged("IsImageChanged");
}
}
}
我想要的是当我点击按钮<Button ContentTemplate="{StaticResource ButtonOneDataTemplate}"/>
时,Template
应该替换为{DynamicResource imgDown}
或{DynamicResource imgUp}
。 DataTrigger
取决于IsImageChanged
值。
但是,如果我点击Button
,则DataTrigger
未被触发(Controltemplates
,例如imgUp
,imgDown
未被更改)。如何从我的ViewModel实现这一目标?
答案 0 :(得分:2)
问题是DataGrid列不是可视化树的一部分,因此它不会继承DataContext。为了能够在ButtonOneDataTemplate中使用DataTriggers,您需要使用该模板的按钮具有正确的DataContext。有一个技巧,如何为不在VisualTree中的元素提供DataContext,描述为here
将该解决方案应用于您的代码,我们将拥有以下内容:
代理
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}
Window.Resources
<local:BindingProxy x:Key="proxy" Data="{Binding}" />
<DataTemplate x:Key="ButtonOneDataTemplate">
<Control x:Name="theControl" Template="{DynamicResource imgNo}" Foreground="Orange"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.IsImageChanged}" Value="True">
<Setter TargetName="theControl" Property="Template" Value="{DynamicResource imgUp}" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.IsImageChanged}" Value="False">
<Setter TargetName="theControl" Property="Template" Value="{DynamicResource imgDown}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
HeaderTemplate中
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<Border Background="Violet">
<StackPanel>
<Button ContentTemplate="{StaticResource ButtonOneDataTemplate}"
DataContext="{Binding Path=Data, Source={StaticResource proxy}}"
Command="{Binding DataContext.ButtonClick, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding DataContext, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
</StackPanel>
</Border>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>