如何在AutoGeneratingColumn事件期间根据其值设置数据网格单元格的背景
本文关键字:置数据 网格 单元格 背景 AutoGeneratingColumn 事件 | 更新日期: 2023-09-27 18:14:18
我仍然在与单元格背景的操纵作斗争,所以我问一个新的问题。
用户" h.b. "我写过,我可以在AutoGeneratingColumn事件期间设置单元格样式-根据值更改DataGrid单元格颜色。问题是我不知道该怎么做。
我想要的:根据每个单元格的值设置不同的背景颜色。如果值是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;
}
}
}
这只是伪代码。在列自动生成期间,这样的事情是可能的吗?如果是这样,我如何编辑我的代码,使其有效?
我读了关于值转换器,但我想知道它是否在某种程度上是可能的编程,而不写XAML。
请理解,我还是c#/WPF/DataGrid的初学者。
解决方案part1:
我用了我接受的答案。把它放到
<Window.Resources>
<local:ValueColorConverter x:Key="colorConverter"/>
<Style x:Key="DataGridCellStyle1" TargetType="{x:Type DataGridCell}">
<Setter Property="Padding" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
<Border.Background>
<MultiBinding Converter="{StaticResource colorConverter}">
<Binding RelativeSource="{RelativeSource AncestorType=DataGridCell}" Path="Content.Text"/>
<Binding RelativeSource="{RelativeSource AncestorType=DataGridCell}" Path="IsSelected"/>
</MultiBinding>
</Border.Background>
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
并为它做了一个MultiBinding
转换器,这样我也可以设置所选单元格的背景颜色。
问题:
现在我只需要解决设置空单元格焦点的问题。有提示吗?
<Style.Triggers>
<Trigger Property="HasContent" Value="False">
<Setter Property="Focusable" Value="False"/>
</Trigger>
</Style.Triggers>
这行不通。我在空单元格中有空字符串,但它们被' null '填充,所以应该可以工作,对吧?或者我做错了什么:| ?
解决方案第2部分:所以上面的代码不会工作,只要单元格值是一个' TextBox ',所以我决定找到另一种方法来处理它,可以在这里找到我的答案:https://stackoverflow.com/a/16673602/2296407
谢谢你的帮助
我可以为你的问题提出两种不同的解决方案:第一种是"代码隐藏风格"(你要求的,但我个人认为这在WPF中不是正确的方法)和更多的WPF风格(更棘手,但保持代码隐藏干净,并利用样式,触发器和转换器)
<标题>解决方案1。用于着色的事件处理和代码隐藏逻辑首先,您选择的方法不能直接工作—AutoGeneratingColumn事件用于更改整个列的外观,而不是逐个单元格。因此,它可以用于,例如,根据它的显示索引或绑定属性将正确的样式附加到整个列。
一般来说,事件第一次引发时,您的数据网格将根本没有任何行(因此—单元格)。如果您确实需要捕捉事件—考虑您的DataGrid。LoadingRow事件。你将不能够得到单元格那么容易:)
所以,你要做的是:处理LoadingRow事件,获得行(它有Item属性,它持有(令人惊讶的是))你的绑定项),获得绑定项,进行所有需要的计算,获得你需要改变的单元格,最后改变目标单元格的样式。
下面是代码(作为项目,我使用了一个带有int "Value"属性的示例对象,用于着色)。
XAML
<DataGrid Name="mygrid" ItemsSource="{Binding Items}" AutoGenerateColumns="True" LoadingRow="DataGrid_OnLoadingRow"/>
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;
}
<标题>解决方案2。WPF-style h1> 解决方案仅在值到颜色的转换中使用代码隐藏(假设着色的逻辑比相等比较更复杂——在这种情况下,您可以使用触发器而不用混淆转换器)。
你要做的:设置DataGrid。CellStyle属性,其样式包含一个数据触发器,它检查单元格是否在所需的列内(基于它的DisplayIndex),如果是-通过转换器应用背景。
XAML
<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
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();
}
}
UPD:如果您需要为整个数据网格上色,XAML要简单得多(不需要使用触发器)。使用下面的CellStyle:
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text, Converter={StaticResource colorconverter}}"/>
</Style>
</DataGrid.CellStyle>
标题>标题>
我的意思是,您可以设置列的CellStyle
属性,您不能直接操作单元格,因为它们在此事件中不可用。样式可以包含DataTriggers
形式的条件逻辑(将需要一个转换器,因为您有"小于"和不等于)和Setters
。
此外,如果逻辑不是特定于列,则可以在网格本身上全局设置样式。使用事件的目的是操纵您无法访问的列属性。
我不确定这个属性(Cell.Style)是否在您的WPF Datagrid中可用。在你的情况下可能存在其他选择。它适用于WinForms数据网格。
cell.Style.BackColor = System.Drawing.Color.Black;