C# 如何在自动生成列事件期间根据其值设置datagrid单元格的背景?
我仍在与细胞背景的操纵作斗争,所以我要问一个新问题 一位用户“H.B.”写道,我实际上可以在事件期间设置单元格样式-。问题是我不知道怎么做 我想要什么: 根据每个单元格的值设置不同的背景色。如果该值为C# 如何在自动生成列事件期间根据其值设置datagrid单元格的背景?,c#,wpf,datagrid,background,autogeneratecolumn,C#,Wpf,Datagrid,Background,Autogeneratecolumn,我仍在与细胞背景的操纵作斗争,所以我要问一个新问题 一位用户“H.B.”写道,我实际上可以在事件期间设置单元格样式-。问题是我不知道怎么做 我想要什么: 根据每个单元格的值设置不同的背景色。如果该值为null,我也希望它不是可点击的(我猜是可聚焦的) 我所拥有的/我正在努力做的: private void mydatagrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { fo
null
,我也希望它不是可点击的(我猜是可聚焦的)
我所拥有的/我正在努力做的:
private void mydatagrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
foreach (Cell cell in e.Column)
{
if (cell.Value < 1)
{
cell.Background = Color.Black;
cell.isFocusable = false;
}
else
{
cell.Background = Color.Pink;
}
}
}
这不管用。我在空单元格中有空字符串,但它们都是空的,所以应该可以工作,对吗?或者我做错了什么:|
解决方案第2部分:
因此,只要单元格值是“文本框”,上面的代码就不起作用,因此我决定找到另一种处理方法,可以在我的答案中找到:
感谢您尝试帮助我:)我不确定此属性(Cell.Style)是否在您的WPF数据网格中可用。在你的情况下可能存在一些替代方案。它已经为WinForms datagrid工作
cell.Style.BackColor = System.Drawing.Color.Black;
我的意思是,您可以设置列的属性,您不能直接操作单元格,因为它们在本事件中不可用。样式可以包含
DataTriggers
形式的条件逻辑(需要一个转换器,因为您有“小于”和“不等于”)和Setters
此外,如果逻辑不是特定于列,则可以设置逻辑本身。使用此事件的目的是操作您无法访问的列属性。我可以为您的问题提出两种不同的解决方案:第一种是“代码隐藏样式”(您要求使用此样式,但我个人认为它在WPF中不正确),另一种是WPF样式(这更复杂,但保持代码干净,并利用样式、触发器和转换器) 解决方案1.事件处理和着色代码隐藏逻辑 首先,您选择的方法不会直接起作用-AutoGeneratingColumn事件用于更改整个列的外观,而不是逐个单元格。因此,它可以用于(例如)根据显示索引或绑定属性将正确的样式附加到整个列 一般来说,第一次发生事件时,DATAGRID将没有任何行(因此是单元格)。如果你真的需要捕获这个事件,那么就考虑你的DATAGIDID.LoopIn Reo事件,而你将无法得到简单的单元: 因此,您要做的是:处理LoadingRow事件,获取行(它具有保存绑定项的Item属性(令人惊讶:)),获取绑定项,进行所有需要的计算,获取需要更改的单元格,最后更改目标单元格的样式 下面是代码(作为项,我使用了一个带有int“Value”属性的示例对象,该属性用于着色) XAML
<DataGrid Name="mygrid" ItemsSource="{Binding Items}" AutoGenerateColumns="True" LoadingRow="DataGrid_OnLoadingRow"/>
<DataGrid Name="mygrid" ItemsSource="{Binding Items}" AutoGenerateColumns="True">
<DataGrid.Resources>
<local:ValueColorConverter x:Key="colorconverter"/>
</DataGrid.Resources>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.DisplayIndex}" Value="1">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text, Converter={StaticResource colorconverter}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>
.CS
private void DataGrid_OnLoadingRow(object sender, DataGridRowEventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => AlterRow(e)));
}
private void AlterRow(DataGridRowEventArgs e)
{
var cell = GetCell(mygrid, e.Row, 1);
if (cell == null) return;
var item = e.Row.Item as SampleObject;
if (item == null) return;
var value = item.Value;
if (value <= 1) cell.Background = Brushes.Red;
else if (value <= 2) cell.Background = Brushes.Yellow;
else cell.Background = Brushes.Green;
}
public static DataGridRow GetRow(DataGrid grid, int index)
{
var row = grid.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
if (row == null)
{
// may be virtualized, bring into view and try again
grid.ScrollIntoView(grid.Items[index]);
row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
}
return row;
}
public static T GetVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
var v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T ?? GetVisualChild<T>(v);
if (child != null)
{
break;
}
}
return child;
}
public static DataGridCell GetCell(DataGrid host, DataGridRow row, int columnIndex)
{
if (row == null) return null;
var presenter = GetVisualChild<DataGridCellsPresenter>(row);
if (presenter == null) return null;
// try to get the cell but it may possibly be virtualized
var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
if (cell == null)
{
// now try to bring into view and retreive the cell
host.ScrollIntoView(row, host.Columns[columnIndex]);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
}
return cell;
}
private void DataGrid\u OnLoadingRow(对象发送方,DataGridRowEventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Render,新操作(()=>AlterRow(e));
}
私有void AlterRow(DataGridRowEventArgs e)
{
var cell=GetCell(mygrid,即第1行);
if(cell==null)返回;
var item=e.Row.item作为SampleObject;
如果(item==null)返回;
var值=项目价值;
if(您可以在grid.Auto-generated单元格的rowdabund事件中尝试此值,当然,它有“content”-它是(这就是为什么我在回答中使用content.Text):)尝试使用@Moriancer谢谢你的帮助。我以另一种方式处理空单元格,因为DataTrigger不想与我一起工作,我已经非常生气了:D。但真的谢谢你的支持。@好朋友,没问题。在你的答案中添加了一些代码样式的注释,尽管它更像是假代码=伪代码:)(虽然我也有同样的问题,但我正在寻找CodeBehind中的解决方案您应该实现一个“小于转换器”或者类似,因为IsFocusable
也应该更改。感谢这个非常长且有用的答案。转换器工作良好,我认为,但这些单元格不想着色。我尝试编辑设置,而且我正在使用双值。-编辑了一点。但仍然。我对数据绑定不够友好。是否你认为可能有问题吗?我正在用datatable从dataset的c代码中填充datagrid。我在convertor中获得了正确的值,但它不会给我的单元格背景上色:'(请发布一段用于绑定网格和着色的代码(XAML+代码隐藏)所以我可以检查出哪里出了问题?好吧,如果有什么愚蠢的事情,请不要笑。但问题是,我在datagrid中需要的东西并不总是相同的数量(行/列的数量)因此,我用这些东西填充一个数据表,并将该表放入dataset,只是因为它以某种方式工作。我总是使用以下代码通过单击按钮来填充datagrid数据:mydatagrid.ItemsSource=dataset.Tables[0].DefaultView;
它可以工作,但我不确定如何将这种填充网格与背景色的设置连接起来。我没有在xaml中编写任何关于绑定的内容,只要这样做就可以了。我使用的是u发布的代码。只是将int替换为double everywhere,因为我的值是double。我真的不明白c应该如何使用XAML中的ode工作。我得到了触发器,但我不明白绑定是如何工作的。中的那个。你能帮我理解一下吗?
private void DataGrid_OnLoadingRow(object sender, DataGridRowEventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => AlterRow(e)));
}
private void AlterRow(DataGridRowEventArgs e)
{
var cell = GetCell(mygrid, e.Row, 1);
if (cell == null) return;
var item = e.Row.Item as SampleObject;
if (item == null) return;
var value = item.Value;
if (value <= 1) cell.Background = Brushes.Red;
else if (value <= 2) cell.Background = Brushes.Yellow;
else cell.Background = Brushes.Green;
}
public static DataGridRow GetRow(DataGrid grid, int index)
{
var row = grid.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
if (row == null)
{
// may be virtualized, bring into view and try again
grid.ScrollIntoView(grid.Items[index]);
row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
}
return row;
}
public static T GetVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
var v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T ?? GetVisualChild<T>(v);
if (child != null)
{
break;
}
}
return child;
}
public static DataGridCell GetCell(DataGrid host, DataGridRow row, int columnIndex)
{
if (row == null) return null;
var presenter = GetVisualChild<DataGridCellsPresenter>(row);
if (presenter == null) return null;
// try to get the cell but it may possibly be virtualized
var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
if (cell == null)
{
// now try to bring into view and retreive the cell
host.ScrollIntoView(row, host.Columns[columnIndex]);
cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
}
return cell;
}
<DataGrid Name="mygrid" ItemsSource="{Binding Items}" AutoGenerateColumns="True">
<DataGrid.Resources>
<local:ValueColorConverter x:Key="colorconverter"/>
</DataGrid.Resources>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.DisplayIndex}" Value="1">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text, Converter={StaticResource colorconverter}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>
public class ValueColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var str = value as string;
if (str == null) return null;
int intValue;
if (!int.TryParse(str, out intValue)) return null;
if (intValue <= 1) return Brushes.Red;
else if (intValue <= 2) return Brushes.Yellow;
else return Brushes.Green;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text, Converter={StaticResource colorconverter}}"/>
</Style>
</DataGrid.CellStyle>