当我选择一个单元格时,我想在我的数据网格的行标题(行选择的指示器)中显示一个图标。我在下面的图片中看到了DataGridSelectionUnit.Row和RelativeSourceMode.FindAncestor,typeof(DataGridRow,1),但是我需要它与DataGridSelectionUnit.Cell一起使用。
我想技巧就在于绑定,但是不知道必须将哪个属性链接到绑定:
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
答案 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;
}
}