好的,无论出于何种原因,您想要实现的目标实际上在 WPF 中非常困难。
问题是,正如您所发现的,在 WPF 中,您无法迭代给定行的单元格。所以你有2个选择:
迭代 VisualTree 中的单元格。我强烈反对这个选项,因为首先,如果您使用虚拟化,它会非常糟糕,其次,它非常难看。
在您的 viewModel 上设置一个特殊属性,并通过 DataGrid.CellStyle 将 dataGridCell 的背景属性绑定到此属性。这里的问题是不能直接绑定,因为 DataGridCell 的 datacontext 是对应于单元格所属行的 ViewModel(看图...),而不是单元格所代表的项的属性。所以它变得相当复杂,因为你必须做一种“传递”的投标。
我建议你看看这里:
将单元格对象的属性绑定到 WPF DataGrid 中的 DataGridCell
和这里:
如何动态设置 WPF DataGridCell 样式
这第二个链接解释了我如何做你想要实现的完全相同的事情,以及这种方法的缺点:缓慢......(阅读问题,而不是答案)
这样做,然后您可以迭代项目并在 ViewModel 中设置属性值。
编辑:这是给你的一些代码(根据你的问题)
<local:CellViewModelToTagConverter x:Key="CellViewModelToTagConverter" />
<DataGrid AutoGenerateColumns="False"
EnableRowVirtualization="True"
ItemsSource="{Binding}"
Margin="12,236,12,0"
Name="conflictedDevicesDataGrid"
RowDetailsVisibilityMode="VisibleWhenSelected"
Grid.ColumnSpan="2"
AlternatingRowBackground="#2FFF0000"
IsManipulationEnabled="False">
<DataGrid.Columns>
<!--binding to the Text property of the CellViewModel for the column n°0-->
<DataGridTextColumn Binding="{Binding [0].Text}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<!--this part is the most important, this is where you transfer the right dataContext to the cell-->
<Setter Property="Tag">
<Setter.Value>
<MultiBinding Converter="{StaticResource CellViewModelToTagConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged">
<Binding />
<Binding RelativeSource="{x:Static RelativeSource.Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
<!--and here, you bind the Background property-->
<Setter Property="Background" Value="{Binding Tag.Background, RelativeSource={RelativeSource Self}, Mode=OneWay}" />
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
这是转换器背后的代码:
public class CellViewModelToTagConverter : MarkupExtension, IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var row = values[0] as MyRowViewModel;
var cell = values[1] as DataGridCell;
if (row != null && cell != null)
{
var column = cell.Column as DataGridColumn;
if (column != null)
cell.SetBinding(FrameworkElement.TagProperty, new Binding {
Source = row[column.DataGridOwner.Columns.IndexOf(column)],
BindsDirectlyToSource = true
});
}
return DependencyProperty.UnsetValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new CellViewModelToTagConverter();
}
}
当然,这意味着您在某处有一个MyRowViewModel:
internal class MyRowViewModel : Collection<MyCellViewModel>, INotifyPropertyChanged
{
}
和一个带有背景依赖属性的MyCellViewModel :
internal class MyCellViewModel : DependencyObject
{
private static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register("Background", typeof(Brush), typeof(MyCellViewModel));
internal Brush Background
{
get { return (Brush)(GetValue(BackgroundProperty)); }
set { SetValue(BackgroundProperty, value); }
}
}
这应该可以解决问题(我希望我没有忘记任何事情,如果我忘记了,您可以随时添加评论)
注意:这当然是我的代码的略微修改版本,因为我的应用程序要复杂得多,而且我没有像这样测试它,所以你可能需要做一些调整。另外,在我的情况下,我必须为每种类型的单元格设置一个 CellViewModel,因为我还动态设置了 Foreground、Font、FontSyle、fontWeight 等属性(因此我的性能问题,顺便说一句)但你可能没问题具有更简单的结构。你只需要根据你的情况调整这个想法。