【问题标题】:DataTrigger binded to property in ViewModel is not fired in the Button of DataGridDataTrigger 绑定到 ViewModel 中的属性不会在 DataGrid 的 Button 中触发
【发布时间】:2016-06-12 11:00:57
【问题描述】:

我创建了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");
           }
    }
}

我想要的是当我点击按钮&lt;Button ContentTemplate="{StaticResource ButtonOneDataTemplate}"/&gt;,那么Template应该被替换为{DynamicResource imgDown}{DynamicResource imgUp}DataTrigger 取决于 IsImageChanged 值。

但是,如果我点击Button,则DataTrigger 不会被触发(ControltemplatesimgUpimgDown 不会更改)。如何从我的 ViewModel 中实现这一点?

【问题讨论】:

  • 请提供完整的视图模型代码。 .
  • 你还是不清楚目标。你想用这个实现什么?
  • @Gopichandar 请查看我更新的问题

标签: c# wpf mvvm controltemplate datatrigger


【解决方案1】:

问题是 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>

标头模板

<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>

【讨论】:

  • 万分感谢,伙计!真的很管用!:) 非常感谢!
猜你喜欢
  • 2013-06-25
  • 1970-01-01
  • 2016-10-28
  • 2012-11-08
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 2017-08-07
相关资源
最近更新 更多