【问题标题】:Get datagridcell by value按值获取datagridcell
【发布时间】:2013-11-22 11:25:32
【问题描述】:

我有一个datagrid,它绑定到一个datatable,每个单元格都有一个唯一的值,所以没有两个单元格具有相同的值。

我想将值为 1 (int32) 的单元格更改为绿色。注意,1 的值是动态的,这只是一个例子,它可以在 1-90 之间。

我已经四处搜索,大多数帮助都会根据坐标(即 (4,2) 或所选单元格)为您提供单元格的值。这不是我想要的,我想根据其值更改单元格的颜色。

有没有办法做到这一点,例如在 JavaScript 中,我会简单地为每个单元格分配一个与其值相等的 id,然后像$('#' + 1).css('background-color:green;') 这样的东西(注意:这可能不是正确的语法,但你明白了) .有没有这样简单的方法或标准的方法?

我的数据网格

<DataGrid Name="grid" ItemsSource="{Binding}" Height="300" Width="900"
          AutoGenerateColumns="True"
          VerticalScrollBarVisibility="Disabled" HorizontalAlignment="Center" VerticalAlignment="Top" RowHeight="40">
            <DataGrid.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel Orientation="Vertical" />
                </ItemsPanelTemplate>
            </DataGrid.ItemsPanel>
        </DataGrid>

表创建

DataSet dataSet = new DataSet("myDS");
            DataTable numbersTable = new DataTable("Numbers");
            numbersTable.Columns.Add("Number", typeof(Int32));
            for (int i = 1; i < 91; i++)
            {
                numbersTable.Rows.Add(i);
            }
            dataSet.Tables.Add(numbersTable);
            grid.DataContext = numbersTable.DefaultView;

【问题讨论】:

  • 您是否尝试通过遍历数据网格的每一行(foreach)来找到所需的值?我的意思是找到具有所需值的单元格的坐标,然后应用样式或其他...只是一个建议。
  • 你能把这个作为答案,看看它是否有帮助?

标签: c# wpf datagrid datatable datagridcell


【解决方案1】:

请看一下这个Change DataGrid cell colour based on values

Public class NameToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string input = value as string;
        switch (input)
        {
            case "John":
                return Brushes.LightGreen;
            default:
                return DependencyProperty.UnsetValue;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

网格:

<DataGridTextColumn Binding="{Binding Name}">
    <DataGridTextColumn.ElementStyle>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="Background" Value="{Binding Name, Converter={StaticResource NameToBrushConverter}}"/>
        </Style>
    </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

画笔:

public string Name
{
    get { return _name; }
    set
    {
        if (_name != value)
        {
            _name = value;
            OnPropertyChanged("Name");
            OnPropertyChanged("NameBrush");
        }
    }
}

public Brush NameBrush
{
    get
    {
        switch (Name)
        {
            case "John":
                return Brushes.LightGreen;
        }

        return Brushes.Transparent;
    }
}

【讨论】:

    【解决方案2】:

    有几种方法可以满足您的要求。这有点不方便,因为我们必须在DataGrid 的列上应用StyleTrigger,而不是DataGrid 本身。这意味着您不能使用AutoGenerateColumns 功能,您必须手动定义它们,如下所示。试试这个:

    <DataGrid ItemsSource="{Binding YourItems}" AutoGenerateColumns="False">
        <DataGrid.Resources>
            <Style x:Key="BackgroundColourStyle" TargetType="{x:Type TextBlock}">
                <Style.Triggers>
                    <Trigger Property="Text" Value="1">
                        <Setter Property="Background" Value="LightGreen" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding YourPropertyName}" 
                ElementStyle="{StaticResource BackgroundColourStyle}">
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
    

    更新>>>

    好的,所以要使用变量值执行此操作,最好以 WPF 以数据为中心的方式执行此操作。与 WPF 中的往常一样,我们希望创建具有所有我们需要在 UI 中显示的属性的数据对象。因此,您需要将一个新的bool 属性添加到您在DataGrid 中显示的任何数据类型类中...如果您坚持使用DataTable,可以为此添加一个新列。

    但是,我建议您使用一个类,如果您创建一个类,则必须确保在其中正确实现 INotifyPropertyChanged 接口。您可以像这样向其中添加属性:

    public int NumberValue { get; set; } // implement `INotifyPropertyChanged` here
    public bool HasHighlightValue { get; set; } // implement `INotifyPropertyChanged` here
    

    然后我们可以使用这个属性来高亮DataGrid中的相关单元格:

    <Style x:Key="BackgroundColourStyle" TargetType="{x:Type TextBlock}">
        <Style.Triggers>
            <Trigger Property="HasHighlightValue" Value="True">
                <Setter Property="Background" Value="LightGreen" />
            </Trigger>
        </Style.Triggers>
    </Style>
    

    最后,您可以在处理程序或代码中设置此新属性以响应某些用户操作:

    // reset previous cell value
    YourDataType previousItem = YourItems.Where(I => i.HasHighlightValue).Single();
    previousItem.HasHighlightValue = false;
    // set new cell value
    YourDataType item = YourItems.Where(I => i.NumberValue == relevantNumber).Single();
    item.HasHighlightValue = true;
    

    【讨论】:

    • 我正在寻找一个动态解决方案,该值只是一个示例,它可以是任何值
    • 动态解是什么意思?
    • 适用于我需要的任何价值的东西,但我自己可能不确定。
    • 与其像这样使用后面的代码,不如使用转换器+DataTrigger的组合来代替?
    • @franssu,如果我错了,请纠正我,但您似乎是在暗示我从您链接到的问题中复制了我的答案,仅基于我在测试项目中使用的Color。就我个人而言,我觉得这很侮辱......好像我不能在不复制的情况下想出Trigger。如果那是你的意思,那么谢谢......伟大的贡献。如果这不是你的意思,那是什么?
    【解决方案3】:

    您还可以使用以下方法在 DataGridCell 的值发生更改时动态格式化 DataGridCell,使用 DataGridCell 上的 Binding.TargetUpdated 或 Binding.SourceUpdated 事件。

    为此,您必须执行以下操作:

    • 为 DataGrid 上的 AutoGeneratingColumn 事件添加事件处理程序。 例如:

    &lt;DataGrid ItemsSource="{Binding}" AutoGeneratingColumn="OnAutoGeneratingColumn"/&gt;

    • 在 AutoGeneratingColumn 处理程序中,确定自动生成的列是否具有 Binding,如果有,将其上的 NotifyOnTargetUpdated 设置为 true 并在将包含 EventSetter 的列上设置 CellStyle 用于 Binding.TargetUpdatedEvent 事件。例如:

      void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
      {
          BindingBase bindingBase = null;
      
          var dataGridBoundColumn = e.Column as DataGridBoundColumn;
          if (dataGridBoundColumn != null)
          {
              bindingBase = dataGridBoundColumn.Binding;
          }
          else
          {
              var dataGridComboBoxColumn = e.Column as DataGridComboBoxColumn;
              if (dataGridComboBoxColumn != null)
                  bindingBase = dataGridComboBoxColumn.SelectedItemBinding;
          }
      
          var binding = bindingBase as Binding;
          if (binding != null)
          {
              binding.NotifyOnTargetUpdated = true;
      
              e.Column.CellStyle = new Style(typeof(DataGridCell))
              {
                  Setters = 
                  {
                      new EventSetter(Binding.TargetUpdatedEvent, new EventHandler<DataTransferEventArgs>(OnDataGridCellBindingTargetUpdated))
                  }
              };
          }
      }
      
    • 当 OnDataGridCellBindingTargetUpdated 处理程序中的值发生更改时,实现自定义逻辑以格式化 DataGridCell。例如:

      private static void OnDataGridCellBindingTargetUpdated(object sender, DataTransferEventArgs e)
      {
          var dataGridCell = (DataGridCell)sender;
      
          // Get context: column and item.
          var column = dataGridCell.Column;
          var item = dataGridCell.DataContext;
      
          // TODO: based on context, format DataGridCell instance.
      }
      

    【讨论】:

      猜你喜欢
      • 2014-10-22
      • 1970-01-01
      • 1970-01-01
      • 2015-05-14
      • 1970-01-01
      • 1970-01-01
      • 2014-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多