简体   繁体   English

从 C# 代码隐藏绑定 DataGridTextColumn 颜色

[英]Binding DataGridTextColumn color from C# codebehind

Similar to WPF - help converting XAML binding expression to codebehind类似于WPF - 帮助将 XAML 绑定表达式转换为代码隐藏

I am attempting to use Binding to change the color of certain elements in a DataGridTextColumn.我正在尝试使用绑定来更改 DataGridTextColumn 中某些元素的颜色。 Because I need an arbitrary number of DataGrids in separate tabs, I am creating them iteratively in the codebehind.因为我需要在单独的选项卡中使用任意数量的 DataGrid,所以我在代码隐藏中迭代地创建它们。 Here is my code for creating the column:这是我创建列的代码:

// create a value column
column = new DataGridTextColumn();
column.Binding = new Binding("Value");
BindingOperations.SetBinding(column, DataGridTextColumn.ForegroundProperty, new Binding("TextColor"));
listGrid.Columns.Add(column);

The Value binding works fine, but the TextColor property's getter never gets called. Value 绑定工作正常,但 TextColor 属性的 getter 永远不会被调用。

The grid's ItemsSource property is set to a list of VariableWatcher objects, and here are some of its properties:网格的 ItemsSource 属性设置为 VariableWatcher 对象列表,以下是它的一些属性:

public bool Value
{
    get { return _variable.Value; }
}
// used to set DataGridTextColumn.Foreground
public Brush TextColor
{
    get
    {
        Color brushColor;
         if (_valueChanged)
            brushColor = Color.FromRgb(255, 0, 0);
        else
            brushColor = Color.FromRgb(0, 0, 0);
         return new SolidColorBrush(brushColor);
    }
}

VariableWatcher implements INotifyPropertyChanged as follows: VariableWatcher 实现 INotifyPropertyChanged 如下:

public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string info)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

In one of VariableWatcher's methods, I have the following lines:在 VariableWatcher 的方法之一中,我有以下几行:

_valueChanged = true;
NotifyPropertyChanged("Value");
NotifyPropertyChanged("TextColor");

Stepping over the "Value" line activates a breakpoint in the Value getter, and the Value text is updated in the display.跨过“Value”行会激活 Value getter 中的断点,并且显示中的 Value 文本会更新。 However, stepping over the "TextColor" line does NOT activate the breakpoint in the TextColor getter, and the text color does not change.但是,跨过“TextColor”行不会激活 TextColor getter 中的断点,并且文本颜色不会改变。 Any idea what's going on here?知道这里发生了什么吗?

EDIT: Here is the answer, thanks to Damascus.编辑:这是答案,感谢大马士革。 (I would have put this in a comment on his answer, but it wouldn't format my code properly.) I added this to the XAML file: (我会将其放在对他的回答的评论中,但它不会正确格式化我的代码。)我将其添加到 XAML 文件中:

<Window.Resources>
    <Style x:Key="BoundColorStyle" TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="{Binding TextColor}" />
    </Style>
</Window.Resources>

and in the C# code, I replaced the BindingOperations line with在 C# 代码中,我将 BindingOperations 行替换为

column.ElementStyle = this.FindResource("BoundColorStyle") as Style;

Workaround for this:解决方法:

Create a style in your resources, looking like that:在您的资源中创建一个样式,如下所示:

<Style x:Key="MyStyle" TargetType="{x:Type TextBlock}">
  <Setter Property="Foreground" Value="{Binding TextColor}" />
</Style>

And set this style in the ElementStyle property of your DataGridColumn , should be something like that in your code:并在您的DataGridColumnElementStyle属性中设置此样式,在您的代码中应该是这样的:

column = new DataGridTextColumn();
column.Style = this.FindResource("MyStyle") as Style;

The reason for it being that ElementStyle directly works in the column's Content (ie. the TextBlock displaying a value)原因是ElementStyle直接在列的内容中工作(即显示值的TextBlock

It can be achieved through code behind as well without style.它可以通过代码隐藏以及没有样式来实现。 The important point is to set binding source explicitly (look in below code) for new binding expression that is set for target property .重要的一点是为目标属性设置的新绑定表达式显式设置绑定源(查看下面的代码)

In this example, DataGrid generates dynamic columns and is bounded with an object of ColloectionViewSource (ie cycleDataview) and the source of cycleDataview is an object of ObservableCollection that is cycleRecord.在本例中,DataGrid 生成动态列,并以ColloectionViewSource 对象(即cycleDataview)为界,cycleDataview 的源是ObservableCollection 对象cycleRecord。

// Create view source

this.cycleDataview = new CollectionViewSource();
this.cycleDataview.Source = this.cycleRecords;

 // Set Item Source to data grid
 this.DataGridCycleData.ItemsSource = this.cycleDataview.View;

// Generate Columns for datagrid
 var columns = this.cycleRecords.First().CyclePartCols.Select((x, i) => new {PreDescriptor =  x.PreDescriptor, Index = i }).ToArray();

foreach (var column in columns)
{

  Binding binding = new Binding(string.Format("CyclePartCols[{0}].PartValue", column.Index));

  Binding bindingColor = new Binding(string.Format("CyclePartCols[{0}].TextColor", column.Index));
  **bindingColor.Source = this.cycleRecords;** // Binding source is required to set

  DataGridTextColumn dgc = new DataGridTextColumn();


  txtblckCol.Text = column.PreDescriptor;
  dgc.Header = txtblckCol;
  dgc.Binding = binding;
  this.DataGridCycleData.Columns.Add(dgc);
  BindingOperations.SetBinding(dgc, DataGridTextColumn.ForegroundProperty, bindingColor);                

} }

Use the workaround from damascus but only with code behind:使用大马士革的解决方法,但仅限于背后的代码:

var myStyle = new Style
{
   TargetType = typeof(TextBlock)
};
textColumnStyleExt.Setters.Add(new Setter(TextBlock.ForegroundProperty, new Binding("TextColor"));
column = new DataGridTextColumn();
column.Binding = new Binding("Value");
column.ElementStyle = myStyle;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM