WPF - ItemControl with DataGrids -如何更改模型中行的背景色[MVVM]

8nuwlpux  于 2023-04-07  发布在  其他
关注(0)|答案(1)|浏览(207)

我有一个item控件,它将使用来自ObservableCollection TrayTypesDataGrids的数据填充datagrids

private ObservableCollection<TrayTypeDataGrid> trayTypesDataGrids;
public class TrayTypeDataGrid : ViewModelBase
{
    private ObservableCollection<TrayType> trayTypes;
    public ObservableCollection<TrayType> TrayTypes
    {
        get => trayTypes;
        set
        {
            trayTypes = value;
            OnPropertyChanged(nameof(TrayTypes));
        }
    }
    private ICommand selectionChangedCommand;
    public ICommand SelectionChangedCommand
    {
        get
        {
            return selectionChangedCommand ?? (selectionChangedCommand = new CommandHandler((param) => SelectionChanged(param), true));
        }
    }

    public TrayTypeDataGrid(ObservableCollection<TrayType> trayTypes)
    {
        this.trayTypes = trayTypes;
    }

    private void SelectionChanged(object args)
    {
        TrayType SelectedTrayType = ((TrayType)((SelectionChangedEventArgs)args).AddedItems[0]);
    }
}
<ItemsControl x:Name="DataGridControl" ItemsSource="{Binding TrayTypesDataGrids}" HorizontalAlignment="Center" DockPanel.Dock="Top">
    <ItemsControl.Template>
        <ControlTemplate>
            <DockPanel IsItemsHost="True" Height="{Binding Path=ActualHeight, ElementName=DataGridControl}"/>
        </ControlTemplate>
    </ItemsControl.Template>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <DataGrid Style="{StaticResource DataGridStyleDetails}" ItemsSource="{Binding TrayTypes}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="ID" Binding="{Binding ID}" ElementStyle="{StaticResource TBColumn}"/>
                    <DataGridTextColumn Header="Name" Binding="{Binding Name}" ElementStyle="{StaticResource TBColumn}"/>
                    <DataGridTextColumn Header="D" Binding="{Binding D}" ElementStyle="{StaticResource TBColumn}"/>
                    <DataGridTextColumn Header="W" Binding="{Binding W}" ElementStyle="{StaticResource TBColumn}"/>
                </DataGrid.Columns>
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged" >
                        <i:InvokeCommandAction Command="{Binding SelectionChangedCommand}" PassEventArgsToCommand="True"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </DataGrid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

这样就可以正确填充所有的DataGrid,并且SelectionChanged会获取TrayTypeDataGrid类中的行。但是,我想在选择更改时捕获,并从ItemControl中选择每个DataGrid上的匹配行。如何从ItemControl访问这些DataGrid并设置其选定行或更改匹配行的背景?
我认为这在MVVM中是不可能的,对吗?

zxlwwiss

zxlwwiss1#

这里的主要挑战是WPF MultiSelector的(DataGrid继承的)SelectedItems属性不是DependencyProperty。这使得直接绑定是不可能的。
有很多黑客可以绕过这个问题。这个问题有几个答案可以引导你走向正确的方向,但没有一个提供了一个完整的解决方案,我会赞同,所以我不会简单地宣布这是一个重复:
Bind to SelectedItems from DataGrid or ListBox in MVVM
Brian Hinchey的答案-它子类化了DataGrid并添加了一个new SelectedItems属性,我认为这是最接近的,但并不完整,因为它不允许通过绑定设置选择(只能检索它)。要处理设置,您需要在声明新的SelectedItems DP时通过回调PropertyMetadata来处理属性更改,如下所示:

public static readonly DependencyProperty SelectedItemsProperty =
    DependencyProperty.Register(
         "SelectedItems", 
         typeof(IList), 
         typeof(MyNewDataGridClass), 
         new PropertyMetadata(
              default(IList), 
              new PropertyChangedCallback((d, e) => 
              {
                   if (_isUISelectionChangePending) 
                        return;
                   ((DataGrid)d).SelectedItems.Clear();
                   if (e.NewValue is IList list)
                        ((DataGrid)d).SelectedItems.AddRange(list);
              })));

   private bool _isUISelectionChangePending = false;

   protected override void OnSelectionChanged(SelectionChangedEventArgs e)
   {
         _isUISelectionChangePending = true;
         try
         {
              base.OnSelectionChanged(e);
              SetValue(SelectedItemsProperty, base.SelectedItems);
         }
         finally
         {
              _isUISelectionChangePending = false;
         }
   }

(You还需要确保您的DP更改处理程序不会在OnSelectionChanged处理程序期间执行,该处理程序由UI引起的选择更改触发,因此使用了_isUISelectionChangePending技巧)。
如果你能做到这一点,那么事情就变得简单了:将每个MyNewDataGridClass(双向)绑定到视图模型上的IList SelectedItems属性。如果设置正确,任何网格上的UI引起的选择更改将传播到视图模型属性,然后返回到其他网格。

相关问题