如何基于DependencyProperty设置DataRowView的背景颜色?

时间:2018-12-12 22:35:02

标签: c# wpf datagrid

我的应用程序的最终目标是让用户比较2个数据表。我有2个DataGrid并排显示,显示了DataTables,行已重新排列,以便2个表之间的所有匹配行都对齐。

我的愿望是希望所有不匹配行都具有红色背景,例如:Yes I know this screenshot was made in WinForms

我的XAML设置类似于this question

<DataGrid Name="comparisonGridLeft" ItemsSource="{Binding}" Margin="3" CanUserResizeRows="False">
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Match}" Value="true">
                    <Setter Property="Background" Value="Red"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.RowStyle>
</DataGrid>

在我的DependencyProperty中,“匹配”的定义类似于this answer

public class CustomProperties
{
  public static DependencyProperty MatchProperty =
        DependencyProperty.RegisterAttached("Match",
                                            typeof(bool),
                                            typeof(CustomProperties),
                                            new PropertyMetadata(null));
  public static void SetMatch(DependencyObject obj, bool value)
  {
     obj.SetValue(MatchProperty, value);
  }
  public static bool GetMatch(DependencyObject obj)
  {
     return (bool)(obj.GetValue(MatchProperty));
  }
}

我的最后一个障碍是,当我遍历DataGrid将“ Match”属性设置为正确的值时,出现错误:

  

错误CS1503:参数1:无法从“ System.Data.DataRowView”转换为“ System.Windows.DependencyObject”

foreach (DataRowView leftRow in leftGrid.ItemsSource)
{
  foreach (DataRowView rightRow in rightGrid.ItemsSource)
  {
     bool foundMatch = DetermineIfMatch(leftRow, rightRow);
     if (foundMatch)
     {
        //Throws the compile-time error
        CustomProperties.SetMatch(leftRow, true);
        foundCloseMatch = true;
        break;
     }
  }
}

在此先感谢您的帮助。 WPF的新手,整天都在努力工作

2 个答案:

答案 0 :(得分:0)

您不能在DataRowView上设置附加属性,因为如您所见,它不是DependencyObject,它是附加属性的必需项。 DataGrid的绑定源是什么?如果您控制该对象,则可以将Match属性保留在该对象中。

请注意...对我来说,您的循环可以只设置背景颜色,实际上并不需要附加的属性。

编辑:从事情的角度来看,我不会在数据表中获取数据,而是您自己的POCO:

class MyPoco
{
  string PropA {get;set}
  string PropB {get;set}
  Color Background {get;set}
}

然后有一个List<MyPoco>并将ItemsSource设置为此。除了自动绑定,您还必须自己定义列并将其绑定到POCO属性:

<DataGrid ItemsSource={Binding Pocos}>
  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding PropA}" />

现在,您可以将样式属性添加到POCO(背景属性)中。然后,您将定义一个DataGrid.RowStyle通过绑定到Background属性来设置Background。

答案 1 :(得分:0)

在这种情况下,您不能使用附加属性。这是解决问题的方法

  1. 定义缓存,保存不匹配的数据行
static class CacheService
{
    public static readonly HashSet<DataRowView> Cache = new HashSet<DataRowView>();
}
  1. 进行比较,建立差异缓存
HashSet<DataRowView> _cache = CacheService.Cache;
foreach (DataRowView leftRow in leftGrid.ItemsSource)
{
  foreach (DataRowView rightRow in rightGrid.ItemsSource)
  {
      bool foundMatch = DetermineIfMatch(leftRow, rightRow);
      if (!foundMatch)
          _cache.Add(leftRow);
  }
}
  1. 调整XAML
<DataGrid Name="comparisonGridLeft" ItemsSource="{Binding}" Margin="3" CanUserResizeRows="False">
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="Background" Value="{Binding Path=., Converter={StaticResource MatchToBrushConverter}}" />
        </Style>
    </DataGrid.RowStyle>
</DataGrid>
  1. 转换器
public class MatchToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        HashSet<DataRowView> _cache = CacheService.Cache; //Get the cache

        return _cache.Contains(value) ? Brushes.Red : Brushes.Transparent;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

仅供参考,我尚未对其进行测试。

希望这会有所帮助。