[英]How to change DataGrid (C#, WPF) cell colour in the code behind (programmatically)
我有一个 DataGrid 并且在后面的代码中添加了列和行。
主窗口.xaml:
<DataGrid Name="dgResult" ItemsSource="{Binding}" AutoGenerateColumns="True" CanUserAddRows="False" ColumnWidth="*"/>
主窗口.xaml.cs:
private void AddItemsToDataGrid()
{
List<Measurement> measurements = new List<Measurement>()
{
new Measurement(){ Address="1", Pressure="10", ErrorTemps=new List<ErrorTemp>()
{
new ErrorTemp(){Temp="10", Error="0.1", IsErrorOK =true}, new ErrorTemp() { Temp = "20", Error = "0.2", IsErrorOK =true }}
},
new Measurement(){ Address="1", Pressure="20", ErrorTemps=new List<ErrorTemp>()
{
new ErrorTemp(){Temp="10", Error="0.2", IsErrorOK =true}, new ErrorTemp() { Temp = "20", Error = "0.3", IsErrorOK =true }}
},
new Measurement(){ Address="1", Pressure="30", ErrorTemps=new List<ErrorTemp>()
{
new ErrorTemp(){Temp="10", Error="0.34", IsErrorOK =true}, new ErrorTemp() { Temp = "20", Error = "0.5", IsErrorOK =false }}
}
};
DataTable dataTable = new DataTable();
dataTable.Columns.Add(nameof(Measurement.Address));
dataTable.Columns.Add(nameof(Measurement.Pressure));
foreach(ErrorTemp error in measurements[0].ErrorTemps)
dataTable.Columns.Add(nameof(error.Error)+"("+error.Temp +")");
List<string> row;
foreach (Measurement measurement in measurements)
{
row = new List<string>() { measurement.Address, measurement.Pressure };
foreach (ErrorTemp error in measurement.ErrorTemps)
row.Add(error.Error);
dataTable.Rows.Add(row.ToArray());
}
dgResult.ItemsSource = dataTable.DefaultView;//bez default view jest źle
}
测量.cs:
namespace DataGridCodeBehind
{
public class Measurement
{
public string Address { get; set; }
public string Pressure { get; set; }
public List<ErrorTemp> ErrorTemps { get; set; }
}
public class ErrorTemp
{
public string Temp { get; set; }
public string Error { get; set; }
public bool IsErrorOK { get; set; }
}
}
我想根据IsErrorOK
值更改单元格背景颜色。 我怎样才能在后面的代码中做到这一点?
如果事先知道 ErrorTemps 的最大数量,则跳过数据表并直接使用测量值
<DataGrid ItemsSource="{Binding Measurements}" AutoGenerateColumns="False" CanUserAddRows="False" ColumnWidth="*">
<DataGrid.Resources>
<DataTemplate x:Key="ErrorTempTemplate" DataType="{x:Type local:ErrorTemp}">
<TextBlock x:Name="txtError" Text="{Binding Error}" ToolTip="{Binding Temp}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsErrorOK}" Value="false">
<Setter TargetName="txtError" Property="Background" Value="Red"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Address" Binding="{Binding Address}"/>
<DataGridTextColumn Header="Pressure" Binding="{Binding Pressure}"/>
<DataGridTemplateColumn Header="Temp1">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding ErrorTemps[0]}" ContentTemplate="{StaticResource ErrorTempTemplate}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Temp2">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding ErrorTemps[1]}" ContentTemplate="{StaticResource ErrorTempTemplate}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
如果它必须是完全动态的,这里有点混乱的解决方案
<DataGrid x:Name="blubb" ItemsSource="{Binding Measurements}" AutoGenerateColumns="True" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" AutoGeneratedColumns="DataGrid_AutoGeneratedColumns" CanUserAddRows="False" ColumnWidth="*">
<DataGrid.Resources>
<Style x:Key="ErrorTempstyle" TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Tag.IsErrorOK, RelativeSource={RelativeSource Self}}" Value="false">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
e.Cancel = e.PropertyName == nameof(Measurement.ErrorTemps);
}
private void DataGrid_AutoGeneratedColumns(object sender, System.EventArgs e)
{
var datagrid = (DataGrid)sender;
var firstItem = (Measurement)datagrid.Items[0];
for (int i = 0; i < firstItem.ErrorTemps.Count; i++)
{
var s = new Style { TargetType = typeof(DataGridCell), BasedOn = (Style)datagrid.Resources["ErrorTempstyle"], Setters = { new Setter(TagProperty, new Binding($"ErrorTemps[{i}]")) } };
datagrid.Columns.Add(new DataGridTextColumn { Header = firstItem.ErrorTemps[i].Temp, CellStyle = s, Binding = new Binding($"ErrorTemps[{i}].Error") });
}
}
如果我在 MainViewModel 构造函数中生成 Measurments,则第二个解决方案工作正常:
public MainViewModel()
{
OpenCommand = new DelegateCommand(OpenHandler);
GenerateList();
}
但是如果我要插入按钮,按下它后我会选择文本文件并生成测量值。 我使用按钮命令来做到这一点。:
主视图模型.cs:
public class MainViewModel : BindableBase
{
public ObservableCollection<Measurement> Measurements { get; set; } //= new ObservableCollection<Measurement>();
public DelegateCommand OpenCommand { get; set; }
public MainViewModel()
{
OpenCommand = new DelegateCommand(OpenHandler);
}
private void OpenHandler()
{
GenerateList();
}
private void GenerateList()
{
Measurements = new ObservableCollection<Measurement>()
{
new Measurement(){ Address="1", Pressure="10", ErrorTemps=new List<ErrorTemp>()
{
new ErrorTemp(){Temp="10", Error="0.1", IsErrorOK =true}, new ErrorTemp() { Temp = "20", Error = "0.2", IsErrorOK =true }, new ErrorTemp() { Temp = "30", Error = "0.41", IsErrorOK =true }}
},
new Measurement(){ Address="1", Pressure="20", ErrorTemps=new List<ErrorTemp>()
{
new ErrorTemp(){Temp="10", Error="0.2", IsErrorOK =true}, new ErrorTemp() { Temp = "20", Error = "0.3", IsErrorOK =true }, new ErrorTemp() { Temp = "30", Error = "0.42", IsErrorOK =true }}
},
new Measurement(){ Address="1", Pressure="30", ErrorTemps=new List<ErrorTemp>()
{
new ErrorTemp(){Temp="10", Error="0.34", IsErrorOK =true}, new ErrorTemp() { Temp = "20", Error = "0.5", IsErrorOK =false }, new ErrorTemp() { Temp = "30", Error = "0.43", IsErrorOK =false }}
}
};
}
在上面的示例中,我简化了代码并在不选择文件的情况下生成了 Measurmenst 列表。 现在我有空的 DataGrid。 如何解决?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.