In einem WPF-Projekt habe ich einige DataGridColumnHeaders
von einem DataGrid
neugestylt, die ein ComboBox
für jedes DataGridColumnHeader
zeigen. Wenn der Benutzer wählt ComboBox
's SelectionChanged
Handler (im Code hinter) aktualisiert eine Array
von ColumnOptionViewModel
Objekte auf der MainWindowViewModel
mit der neuesten Auswahl. An diesem Punkt funktioniert auch Code, wenn in diesem Array doppelte Auswahlen vorhanden sind, und setzt dann eine boolesche IsDuplicate
-Eigenschaft auf den ColumnOptionViewModel
, die Duplikate sind. Die Idee ist, dass ein DataTrigger
abholt die Änderung in IsDuplicate
und ändert die Background
ein TextBlock
im DataTemplate
der ItemTemplate
für die doppelten ComboBox
‚s zu Red
.WPF: DataTrigger nicht feuern
Dieser Auslöser wird jedoch nicht ausgelöst. Die IsDuplicate
Eigenschaften sind in Ordnung, und alles andere funktioniert wie erwartet.
Hat jemand eine Idee, was ich falsch mache?
Vielen Dank im Voraus für jede Hilfe. Hier
ist das XAML für das Fenster:
<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>
Code hinter:
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();
}
}
}
EDIT:
ViewModelBase:
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
können Sie überprüfen, ob eine andere Eigenschaft Textbox Wechsel in Datatrigger funktioniert (zB Fontweight zu Bold) – Arie
@Arie, versucht, FontWeight auf Fett zu ändern, wie vorgeschlagen, aber immer noch nicht feuernd. – Cleve
Wie wird Ihre 'OnPropertyChanged' Methode implementiert? Sie geben den Namen der Eigenschaft nicht weiter, so dass es dort möglicherweise ein Problem gibt (es gibt Implementierungen ohne Parameter, aber nur um sicher zu sein). – Shadowed