动态更改数据网格行单元格前景色wpf
Change datagrid row cell foreground colour dynamically wpf
在我的 WPF 项目中,我有一个数据网格,其中的单元格绑定到不同的东西。这是 xaml:
<DataGrid x:Name="Tasks" CanUserDeleteRows="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Column1" Binding="{Binding C1}"/>
<DataGridTextColumn Header="Column2" Binding="{Binding C2}"/>
<DataGridTextColumn Header="Column3" Binding="{Binding C3}"/>
<DataGridTextColumn Header="Column4" Binding="{Binding C4}"/>
<DataGridTextColumn Header="Column5" Binding="{Binding C5}"/>
<DataGridTextColumn Header="Column6" Binding="{Binding C6}"/>
<DataGridTextColumn Header="Column7" Binding="{Binding C7}"/>
<DataGridTextColumn Header="Column8" Binding="{Binding C8}"/>
</DataGrid.Columns>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Add task" Click="ADDtask_Click" FontSize="11"></MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
这是我的 C# 代码:
public Guid 8 { get; }
public string 7 { get; set; }
public string 6 { get; set; }
public string 5 { get; set; }
public string 4 { get; set; }
public string 3 { get; set; }
public string 2 { get; set; }
public string 1 { get; set; }
public Result(string c1, string c2, string c3, string c4, string c5, string c6, string c7, string c8)
{
this.Identifier = Guid.NewGuid();
this.8 = c1;
this.7 = c2;
this.6 = c3;
this.5 = c4;
this.4 = c5;
this.3 = c6;
this.2 = c7;
this.1 = c8;
}
private void Start_Task_Click(object sender, RoutedEventArgs e)
{
System.Windows.Controls.Button button = (System.Windows.Controls.Button)sender;
Result task = (Result)button.DataContext;
if(...)
{
????
}
else
{
return;
}
}
public string idlestatus = "idle";
private void Button_Click1(object sender, RoutedEventArgs e) //this adds the columns to the datagrid
{
Tasks.Items.Add(new Result(textbox1.Text, textbox2.Text, textbox3.Text, textbox4.Text, textbox5.Text, textbox6.Text, textbox7.Text, idlestatus));
}
我想做一个这样的 if 语句:
if(task.c1 == "...") {
cell.Style.Foreground.Color = ...
}
我怎样才能做到这一点?我试过这样做:
Tasks.CellStyle.Style.Foreground.Color
但它不起作用,我们将不胜感激。
你有一些选择。由于您不使用自动生成的列,因此您可以使用 DataGridColumn
:
的 ElementStyle
属性
<DataGrid x:Name="Tasks">
<DataGrid.Resources>
<Style x:Key="ElementStyle" TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="Text"
Value="Error Predicate Text">
<Setter Property="Foreground"
Value="Red" />
</Trigger>
<Trigger Property="Text"
Value="Good Predicate Text">
<Setter Property="Foreground"
Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Column1"
Binding="{Binding C1}"
ElementStyle="{StaticResource ElementStyle}" />
<DataGridTextColumn Header="Column2"
Binding="{Binding C2}"
ElementStyle="{StaticResource ElementStyle}" />
</DataGrid.Columns>
</DataGrid>
或使用 DataTrigger
:
<DataGrid x:Name="Tasks">
<DataGrid.Columns>
<DataGridTextColumn Header="Column1"
Binding="{Binding C1}" />
<DataGridTextColumn Header="Column2"
Binding="{Binding C2}" />
</DataGrid.Columns>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text}"
Value="Error Predicate Text" />
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>
当触发器应该独占特定列的单个单元格(而不是基于单元格值的整行)时,您必须使用 MultiDataTrigger
检查当前列 header:
<DataGrid x:Name="Tasks">
<DataGrid.Columns>
<DataGridTextColumn Header="Column1"
Binding="{Binding C1}" />
<DataGridTextColumn Header="Column2"
Binding="{Binding C2}" />
</DataGrid.Columns>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.Header}"
Value="Column1" />
<Condition Binding="{Binding C1}" Value="Error Predicate Text" />
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="Red" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>
另一种解决方案是使用 IValueConverter
(或 IMultiValueConverter
,原因与上述 MultiDataTrigger
相同):
<DataGrid x:Name="Tasks">
<DataGrid.Columns>
<DataGridTextColumn Header="Column1"
Binding="{Binding C1}" />
<DataGridTextColumn Header="Column2"
Binding="{Binding C2}" />
</DataGrid.Columns>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Foreground">
<Setter.Value>
<MultiBinding>
<MultiBinding.Converter>
<CellForegroundMultiValueConverter />
</MultiBinding.Converter>
<Binding RelativeSource="{RelativeSource Self}"
Path="Column.Header"/>
<Binding />
<Binding Path="HasChanges" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</DataGrid.CellStyle>
</DataGrid>
CellForegroundMultiValueConverter.cs
class CellForegroundMultiValueConverter : IMultiValueConverter
{
#region Implementation of IMultiValueConverter
/// <inheritdoc />
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var columnHeader = values[0] as string;
var dataItem = values[1] as Result;
return columnHeader.Equals("Column1", StringComparison.OrdinalIgnoreCase)
&& dataItem.C1.Equals("....", StringComparison.OrdinalIgnoreCase)
|| columnHeader.Equals("Column2", StringComparison.OrdinalIgnoreCase)
&& dataItem.C2.Equals("....", StringComparison.OrdinalIgnoreCase)
? Brushes.Red
: Brushes.Black;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotSupportedException();
#endregion
}
Result.cs
class Result : INotifyPropertyChanged
{
private string c1;
public string C1
{
get => this.c1;
set
{
this.c1 = value;
OnPropertyChanged();
this.HasChanegs = true;
}
}
private string c2;
public string C2
{
get => this.c2;
set
{
this.c2 = value;
OnPropertyChanged();
this.HasChanegs = true;
}
}
private bool hasChanges;
public string HasChanges
{
get => this.hasChanges;
set
{
this.hasChanges = value;
OnPropertyChanged();
}
}
}
在我的 WPF 项目中,我有一个数据网格,其中的单元格绑定到不同的东西。这是 xaml:
<DataGrid x:Name="Tasks" CanUserDeleteRows="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Column1" Binding="{Binding C1}"/>
<DataGridTextColumn Header="Column2" Binding="{Binding C2}"/>
<DataGridTextColumn Header="Column3" Binding="{Binding C3}"/>
<DataGridTextColumn Header="Column4" Binding="{Binding C4}"/>
<DataGridTextColumn Header="Column5" Binding="{Binding C5}"/>
<DataGridTextColumn Header="Column6" Binding="{Binding C6}"/>
<DataGridTextColumn Header="Column7" Binding="{Binding C7}"/>
<DataGridTextColumn Header="Column8" Binding="{Binding C8}"/>
</DataGrid.Columns>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="Add task" Click="ADDtask_Click" FontSize="11"></MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
这是我的 C# 代码:
public Guid 8 { get; }
public string 7 { get; set; }
public string 6 { get; set; }
public string 5 { get; set; }
public string 4 { get; set; }
public string 3 { get; set; }
public string 2 { get; set; }
public string 1 { get; set; }
public Result(string c1, string c2, string c3, string c4, string c5, string c6, string c7, string c8)
{
this.Identifier = Guid.NewGuid();
this.8 = c1;
this.7 = c2;
this.6 = c3;
this.5 = c4;
this.4 = c5;
this.3 = c6;
this.2 = c7;
this.1 = c8;
}
private void Start_Task_Click(object sender, RoutedEventArgs e)
{
System.Windows.Controls.Button button = (System.Windows.Controls.Button)sender;
Result task = (Result)button.DataContext;
if(...)
{
????
}
else
{
return;
}
}
public string idlestatus = "idle";
private void Button_Click1(object sender, RoutedEventArgs e) //this adds the columns to the datagrid
{
Tasks.Items.Add(new Result(textbox1.Text, textbox2.Text, textbox3.Text, textbox4.Text, textbox5.Text, textbox6.Text, textbox7.Text, idlestatus));
}
我想做一个这样的 if 语句:
if(task.c1 == "...") {
cell.Style.Foreground.Color = ...
}
我怎样才能做到这一点?我试过这样做:
Tasks.CellStyle.Style.Foreground.Color
但它不起作用,我们将不胜感激。
你有一些选择。由于您不使用自动生成的列,因此您可以使用 DataGridColumn
:
ElementStyle
属性
<DataGrid x:Name="Tasks">
<DataGrid.Resources>
<Style x:Key="ElementStyle" TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="Text"
Value="Error Predicate Text">
<Setter Property="Foreground"
Value="Red" />
</Trigger>
<Trigger Property="Text"
Value="Good Predicate Text">
<Setter Property="Foreground"
Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Column1"
Binding="{Binding C1}"
ElementStyle="{StaticResource ElementStyle}" />
<DataGridTextColumn Header="Column2"
Binding="{Binding C2}"
ElementStyle="{StaticResource ElementStyle}" />
</DataGrid.Columns>
</DataGrid>
或使用 DataTrigger
:
<DataGrid x:Name="Tasks">
<DataGrid.Columns>
<DataGridTextColumn Header="Column1"
Binding="{Binding C1}" />
<DataGridTextColumn Header="Column2"
Binding="{Binding C2}" />
</DataGrid.Columns>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text}"
Value="Error Predicate Text" />
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>
当触发器应该独占特定列的单个单元格(而不是基于单元格值的整行)时,您必须使用 MultiDataTrigger
检查当前列 header:
<DataGrid x:Name="Tasks">
<DataGrid.Columns>
<DataGridTextColumn Header="Column1"
Binding="{Binding C1}" />
<DataGridTextColumn Header="Column2"
Binding="{Binding C2}" />
</DataGrid.Columns>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.Header}"
Value="Column1" />
<Condition Binding="{Binding C1}" Value="Error Predicate Text" />
</MultiDataTrigger.Conditions>
<Setter Property="Foreground" Value="Red" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>
另一种解决方案是使用 IValueConverter
(或 IMultiValueConverter
,原因与上述 MultiDataTrigger
相同):
<DataGrid x:Name="Tasks">
<DataGrid.Columns>
<DataGridTextColumn Header="Column1"
Binding="{Binding C1}" />
<DataGridTextColumn Header="Column2"
Binding="{Binding C2}" />
</DataGrid.Columns>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Foreground">
<Setter.Value>
<MultiBinding>
<MultiBinding.Converter>
<CellForegroundMultiValueConverter />
</MultiBinding.Converter>
<Binding RelativeSource="{RelativeSource Self}"
Path="Column.Header"/>
<Binding />
<Binding Path="HasChanges" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</DataGrid.CellStyle>
</DataGrid>
CellForegroundMultiValueConverter.cs
class CellForegroundMultiValueConverter : IMultiValueConverter
{
#region Implementation of IMultiValueConverter
/// <inheritdoc />
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var columnHeader = values[0] as string;
var dataItem = values[1] as Result;
return columnHeader.Equals("Column1", StringComparison.OrdinalIgnoreCase)
&& dataItem.C1.Equals("....", StringComparison.OrdinalIgnoreCase)
|| columnHeader.Equals("Column2", StringComparison.OrdinalIgnoreCase)
&& dataItem.C2.Equals("....", StringComparison.OrdinalIgnoreCase)
? Brushes.Red
: Brushes.Black;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotSupportedException();
#endregion
}
Result.cs
class Result : INotifyPropertyChanged
{
private string c1;
public string C1
{
get => this.c1;
set
{
this.c1 = value;
OnPropertyChanged();
this.HasChanegs = true;
}
}
private string c2;
public string C2
{
get => this.c2;
set
{
this.c2 = value;
OnPropertyChanged();
this.HasChanegs = true;
}
}
private bool hasChanges;
public string HasChanges
{
get => this.hasChanges;
set
{
this.hasChanges = value;
OnPropertyChanged();
}
}
}