【问题标题】:How to set background color of DataRowView based on DependencyProperty?如何根据DependencyProperty设置DataRowView的背景颜色?
【发布时间】:2019-05-14 02:42:30
【问题描述】:

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

我希望任何 不匹配 行都具有红色背景,如下所示:

我的 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));
  }
}

我的最后一个障碍是,当我遍历 DataGrids 以将“匹配”属性设置为正确的值时,我得到一个错误:

错误 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 新手,整天都在努力,但无济于事????

【问题讨论】:

    标签: c# wpf datagrid


    【解决方案1】:

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

    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();
        }
    }
    

    仅供参考,我没有测试过。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的回答。对于查看此答案的其他人来说,重要的是要注意我需要将转换器添加到 Window.Resources,如 [此处][1] 所示。我能够让它与 2 个转换器一起工作:一个用于左表,一个用于右表。 [1]:wpftutorial.net/ValueConverters.html
    【解决方案2】:

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

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

    编辑:从事物的声音来看,我不会获取数据表中的数据,而是您自己的 POCO:

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

    然后有一个List&lt;MyPoco&gt; 并将 ItemsSource 设置为那个。您必须自己定义列并将它们绑定到 POCO 属性,而不是自动绑定:

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

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

    【讨论】:

    • 感谢您的回答。我正在像这样设置我的绑定源: comparisonGridLeft.ItemsSource = myDataTable.AsDataView();编译器对我在 myDataTable 上设置 Match 属性感到满意,但似乎没有任何更新。您知道我还需要进行哪些其他更改才能使其正常工作吗?
    • 您的旁注似乎要简单得多 - 我需要 DataGridRow 而不是 DataRowView,对吧?我试着走那条路,但遍历 DataGridRows 似乎很难/很难完成
    • @ThomasGales myDataTable 是实际的 DataTable 类型吗?因为那也不是 DependencyObject。如果您这样做,您的代码将不会构建。它是什么样的物体?
    • 它绝对是一个实际的 DataTable 类型,所以我不确定它为什么要编译。
    • @ThomasGales... 如果我尝试写:DataTable dt = new DataTable(); CustomProperties.SetMatch(dt, true);它不会在不是 DependencyObject 的 'dt' 上编译。您可以编辑您的问题以显示更多涉及的代码吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 2015-04-21
    • 1970-01-01
    • 2017-06-17
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    相关资源
    最近更新 更多