繁体   English   中英

WPF:DataTrigger不触发

[英]WPF: DataTrigger not firing

在WPF项目中,我具有一些重新设置样式的DataGridColumnHeadersDataGrid ,它们为每个DataGridColumnHeader显示一个ComboBox 当用户从ComboBox的中SelectionChanged处理程序(在后面的代码中)使用最新的选择更新MainWindowViewModel上的ColumnOptionViewModel对象Array

此时,如果此数组中有任何重复的选择,也可以计算出一些代码,然后在ColumnOptionViewModel上设置重复的IsDuplicate布尔属性。 这个想法是, DataTrigger接收IsDuplicate更改,并将ItemTemplateDataTemplate中用于复制的ComboBoxTextBlockBackground更改为Red

但是,此触发器不会触发。 IsDuplicate属性设置正确,其他所有功能IsDuplicate预期工作。 我究竟做错了什么?

这是Window的XAML:

<Window x:Class="TestDataGrid.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TestDataGrid"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">

 <Grid>
    <DataGrid Grid.Row="1" x:Name="dataGrid" ItemsSource="{Binding Records}">
        <DataGrid.ColumnHeaderStyle>
            <Style TargetType="DataGridColumnHeader">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <StackPanel>
                                <ComboBox x:Name="cbo"
                                          ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},Path=DataContext.ColumnOptions}"
                                          SelectionChanged="cbo_SelectionChanged">

                                     <ComboBox.ItemTemplate>
                                        <DataTemplate>
                                            <TextBlock x:Name="txt" Text="{Binding Name}"/>
                                            <DataTemplate.Triggers>
                                                <DataTrigger Binding="{Binding ElementName=cbo, Path=SelectedItem.IsDuplicate}">
                                                    <Setter TargetName="txt" Property="Background" Value="Red"/>
                                                </DataTrigger>
                                            </DataTemplate.Triggers>
                                        </DataTemplate>
                                    </ComboBox.ItemTemplate>
                                </ComboBox>
                            </StackPanel>   
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.ColumnHeaderStyle>
    </DataGrid>    
</Grid>

代码如下:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainWindowViewModel(RecordProvider.GetRecords());
    }

    private void cbo_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var vm = (MainWindowViewModel)DataContext;

        var selectionChangedCombo = (ComboBox)e.Source;

        var dataGridColumnHeader = selectionChangedCombo.TemplatedParent as DataGridColumnHeader;

        vm.ColumnSelections[dataGridColumnHeader.DisplayIndex] = selectionChangedCombo.SelectedItem as ColumnOptionViewModel;

        CheckForDuplicates();

    }

    private void CheckForDuplicates()
    {
        var vm = (MainWindowViewModel)DataContext;

        var duplicates = vm.ColumnSelections.GroupBy(x => x.Name)
            .Where(g => g.Skip(1).Any())
            .SelectMany(g => g);

        foreach (var option in duplicates)
        {
            option.IsDuplicate = true;
        }
    }
}

MainWindowViewModel:

public class MainWindowViewModel : ViewModelBase
{
    public ObservableCollection<ColumnOptionViewModel> _columnOptions = new ObservableCollection<ColumnOptionViewModel>();
    public ObservableCollection<RecordViewModel> _records = new ObservableCollection<RecordViewModel>();

    ColumnOptionViewModel[] _columnSelections = new ColumnOptionViewModel[3];

    public MainWindowViewModel(IEnumerable<Record> records)
    {
        foreach (var rec in records)
        {
            Records.Add(new RecordViewModel(rec));
        }

        ColumnOptions.Add(new ColumnOptionViewModel(TestDataGrid.ColumnOptions.ColumnOption1));
        ColumnOptions.Add(new ColumnOptionViewModel(TestDataGrid.ColumnOptions.ColumnOption2));
        ColumnOptions.Add(new ColumnOptionViewModel(TestDataGrid.ColumnOptions.ColumnOption3));

        ColumnSelections[0] = ColumnOptions[0];
        ColumnSelections[1] = ColumnOptions[1];
        ColumnSelections[2] = ColumnOptions[2];

    }

    public ObservableCollection<ColumnOptionViewModel> ColumnOptions
    {
        get { return _columnOptions; }
        set { _columnOptions = value; }
    }

    public ColumnOptionViewModel[] ColumnSelections
    {
        get { return _columnSelections; }
        set { _columnSelections = value; }
    }

    public ObservableCollection<RecordViewModel> Records
    {
        get { return _records; }
        set { _records = value; }
    }
}

ColumnOptionViewModel:

public class ColumnOptionViewModel : ViewModelBase
{
    ColumnOptions _colOption;

    public ColumnOptionViewModel(ColumnOptions colOption )
    {
        _colOption = colOption;
    }

    public string Name
    {
        get { return _colOption.ToString(); }
    }

    public override string ToString()
    {
        return Name;
    }

    private bool _isDuplicate = false;
    public bool IsDuplicate
    {
        get { return _isDuplicate; }
        set
        { _isDuplicate = value;
            OnPropertyChanged();
        }
    }
}

编辑:

ViewModelBase:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

如果尝试绑定到ComboBox SelectedItemIsDuplicate属性,则可以使用RelativeSource

您还应该根据希望何时将TextBlockBackground属性设置为Red来将DataTriggerValue属性设置为true / false:

<ComboBox x:Name="cbo" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},Path=DataContext.ColumnOptions}"
                  SelectionChanged="cbo_SelectionChanged">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock x:Name="txt" Text="{Binding Name}"/>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=SelectedItem.IsDuplicate, RelativeSource={RelativeSource AncestorType=ComboBox}}" Value="True">
                    <Setter TargetName="txt" Property="Background" Value="Red"/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

正如@ MM8说,该Value是不是您所选择的DataTrigger

如果这样不起作用,您可以尝试直接在TextBlock上使用Trigger而不是DataTemplate.Triggers

   <TextBlock>
       <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Setter Property="Background" Value="White"/>
                <Style.Triggers>
                   <DataTrigger Binding="{Binding Path=IsDuplicate}" Value="True">
                      <Setter Property="Background" Value="Red"/>
                    </DataTrigger>
                 </Style.Triggers>
              </Style>
         </TextBlock.Style>
      </TextBlock>

同样,具有可选项目的控件中的背景和前景值可能会很棘手。 例如,您可能想禁用默认选择颜色(不幸的是,您将不得不自己管理选定/重点突出的背景):

        <ComboBox.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
        </ComboBox.Resources>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM