选择单元格时在数据网格上显示图标

时间:2020-09-29 08:39:15

标签: wpf datagrid

当我选择一个单元格时,我想在我的数据网格的行标题(行选择的指示器)中显示一个图标。我在下面的图片中看到了DataGridSelectionUnit.Row和RelativeSourceMode.FindAncestor,typeof(DataGridRow,1),但是我需要它与DataGridSelectionUnit.Cell一起使用。

enter image description here

我想技巧就在于绑定,但是不知道必须将哪个属性链接到绑定:

Binding bindingVisibility = new Binding()
        {
            Path = new PropertyPath("IsSelected"),
            RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(DataGridCell),1 ),
            UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
            Converter = new BooleanToVisibilityConverter()
        };
        elemFactory.SetBinding(VisibilityProperty, bindingVisibility); 

谢谢!

致谢

Xabi

2 个答案:

答案 0 :(得分:2)

由于您使用的是SelectionUnit="Cell",所以所选的行处理有些“困难”,不能仅使用XAML来完成:

MainWindow.xaml

<DataGrid SelectionUnit="Cell" 
          DataGridCell.Selected="DataGridCell_OnSelected" 
          DataGridCell.Unselected="DataGridCell_OnUnselected">
  <DataGrid.Resources>
    <ContentControl x:Key="RowHeaderContent" x:Shared="False">
      <Image Source="[path to image]" />
    </ContentControl>
  </DataGrid.Resources>
</DataGrid>

MainWindow.xaml.cs

private void DataGridCell_OnSelected(object sender, RoutedEventArgs e)
{
  var dataGrid = e.Source as DataGrid;
  var selectedCell = e.OriginalSource as DataGridCell;
  object selectedRowItem = selectedCell.DataContext;
  var selectedRow = (DataGridRow) dataGrid.ItemContainerGenerator.ContainerFromItem(selectedRowItem);
  selectedRow.Header = dataGrid.Resources["RowHeaderContent"];
}

private void DataGridCell_OnUnselected(object sender, RoutedEventArgs e)
{
  var dataGrid = e.Source as DataGrid;
  var selectedCell = e.OriginalSource as DataGridCell;
  object selectedRowItem = selectedCell.DataContext;

  // Check if there is still any cell of the same row selected
  if (dataGrid.SelectedCells.Any(cellInfo => cellInfo.Item == selectedRowItem))
  {
    return;
  }

  var selectedRow = (DataGridRow) dataGrid.ItemContainerGenerator.ContainerFromItem(selectedRowItem);
  selectedRow.Header = null;
}

答案 1 :(得分:1)

将选择状态从单元格传播到行有点棘手,但在大多数情况下是可能的。

此解决方案提出了一个附加属性来处理单元格->行选择(以下代码)。

基本思想:每当选择的细胞变化,使用cellInfo项来确定可视树中的当前位置,步行到行,并根据需要更新的行

必须在具有DataGrid附加属性的DataGridSelection.PropagateCellSelection上启用处理,然后对于每个DataGridRow,可以使用DataGridSelection.IsSelected附加属性。

以下代码示例会将行标题背景颜色更改为绿色,您可以使用所需的任何东西替换设置器。 xmlns:local指向定义了DataGridSelection的名称空间。

<DataGrid ItemsSource="{Binding}" SelectionUnit="Cell" local:DataGridSelection.PropagateCellSelection="True">
    <DataGrid.RowHeaderStyle>
        <Style TargetType="DataGridRowHeader">
            <Setter Property="Width" Value="50"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=(local:DataGridSelection.IsSelected),RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}}" Value="True">
                    <Setter Property="Background" Value="Green"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.RowHeaderStyle>
</DataGrid>

附加的属性代码

public static class DataGridSelection
{
    // The DataGridSelection.IsSelected property will be maintained on DataGridRow, if
    // DataGridSelection.PropagateCellSelection is set to true on the DataGrid.

    public static bool GetIsSelected(DataGridRow obj)
    {
        return (bool)obj.GetValue(IsSelectedProperty);
    }

    private static void SetIsSelected(DataGridRow obj, bool value)
    {
        obj.SetValue(IsSelectedPropertyKey, value);
    }

    private static readonly DependencyPropertyKey IsSelectedPropertyKey =
        DependencyProperty.RegisterAttachedReadOnly("IsSelected", typeof(bool), typeof(DataGridSelection), new FrameworkPropertyMetadata());

    public static readonly DependencyProperty IsSelectedProperty = IsSelectedPropertyKey.DependencyProperty;


    // The DataGridSelection.PropagateCellSelection property enables the mechanism of maintaining
    // DataGridSelection.IsSelected state on DataGridRow

    public static bool GetPropagateCellSelection(DataGrid obj)
    {
        return (bool)obj.GetValue(PropagateCellSelectionProperty);
    }

    public static void SetPropagateCellSelection(DataGrid obj, bool value)
    {
        obj.SetValue(PropagateCellSelectionProperty, value);
    }

    public static readonly DependencyProperty PropagateCellSelectionProperty =
        DependencyProperty.RegisterAttached("PropagateCellSelection", typeof(bool), typeof(DataGridSelection), new PropertyMetadata(new PropertyChangedCallback(PropagateCellSelectionChanged)));


    private static void PropagateCellSelectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(d is DataGrid dg)) return;

        // Add or remove the event handler that handles the propagation from cell selection
        // to DataGridSelection.IsSelected on DataGridRow

        if (true.Equals(e.NewValue))
        {
            dg.SelectedCellsChanged -= DataGridCellSelectionChangedHandler;
            dg.SelectedCellsChanged += DataGridCellSelectionChangedHandler;
        }
        else
        {
            dg.SelectedCellsChanged -= DataGridCellSelectionChangedHandler;
        }
    }

    // Determine rows to add / remove the selected state whenever cell selection changes
    private static void DataGridCellSelectionChangedHandler(object s, SelectedCellsChangedEventArgs e)
    {
        if (!(s is DataGrid dg)) return;

        var removeRows = RowsFromCellInfos(e.RemovedCells);
        var selectedRows = RowsFromCellInfos(dg.SelectedCells);

        removeRows.ExceptWith(selectedRows);

        foreach (var row in removeRows)
            SetIsSelected(row, false);
        foreach (var row in selectedRows)
            SetIsSelected(row, true);
    }

    private static ISet<DataGridRow> RowsFromCellInfos(IEnumerable<DataGridCellInfo> cells)
    {
        var rows = new HashSet<DataGridRow>();
        foreach (var cellInfo in cells)
        {
            var cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
            var row = GetParent<DataGridRow>(cellContent);
            if (row != null) rows.Add(row);
        }
        return rows;
    }

    // Helper method for tree traversal
    private static T GetParent<T>(DependencyObject d) where T : DependencyObject
    {
        while (d != null && !(d is T))
            d = VisualTreeHelper.GetParent(d);

        return d as T;
    }
}
相关问题