Zmiana koloru komórki DataGrid na podstawie wartości
Mam datagrid WPF i chcę mieć różne kolory komórek według wartości. Mam poniższy kod na moim xaml
Style TargetType="DataGridCell"
Ale zamiast zaznaczać komórkę tylko jest zaznaczanie całego wiersza? Co przegapiłem?
7 answers
Jeśli spróbujesz ustawić DataGrid.CellStyle
DataContext będzie wierszem, więc jeśli chcesz zmienić kolor na podstawie jednej komórki, najłatwiej będzie to zrobić w określonych kolumnach, zwłaszcza że kolumny mogą mieć różną zawartość, jak bloki tekstowe, Comboboxy i pola wyboru. Oto przykład ustawienia wszystkich komórek jasnozielonych, gdzie Name
jest John
:
<DataGridTextColumn Binding="{Binding Name}">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Text" Value="John">
<Setter Property="Background" Value="LightGreen"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
Można również użyć ValueConverter
aby zmienić kolor.
public class NameToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string input = value as string;
switch (input)
{
case "John":
return Brushes.LightGreen;
default:
return DependencyProperty.UnsetValue;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
Użycie:
<Window.Resources>
<local:NameToBrushConverter x:Key="NameToBrushConverter"/>
</Window.Resources>
...
<DataGridTextColumn Binding="{Binding Name}">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="{Binding Name, Converter={StaticResource NameToBrushConverter}}"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
Kolejną opcją jest bezpośrednie powiązanie Background
z właściwością, która zwraca odpowiednio kolorowy pędzel. Będziesz musiał uruchomić powiadomienia o zmianie właściwości w Ustawieniach właściwości, od których zależy kolor.
Np.
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged("Name");
OnPropertyChanged("NameBrush");
}
}
}
public Brush NameBrush
{
get
{
switch (Name)
{
case "John":
return Brushes.LightGreen;
default:
break;
}
return Brushes.Transparent;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-20 19:05:16
Jeśli chcesz to zrobić z ustawioną liczbą kolumn, najlepszy jest sposób H. B. Ale jeśli nie wiesz, ile kolumn masz do czynienia z uruchomieniem, wtedy poniższy kod [Czytaj: hack] będzie działać. Nie jestem pewien, czy istnieje lepsze rozwiązanie z nieznaną liczbą kolumn. Zajęło mi dwa dni pracy nad nim off I on, aby go dostać, więc trzymam się go niezależnie.
C #
public class ValueToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int input;
try
{
DataGridCell dgc = (DataGridCell)value;
System.Data.DataRowView rowView = (System.Data.DataRowView)dgc.DataContext;
input = (int)rowView.Row.ItemArray[dgc.Column.DisplayIndex];
}
catch (InvalidCastException e)
{
return DependencyProperty.UnsetValue;
}
switch (input)
{
case 1: return Brushes.Red;
case 2: return Brushes.White;
case 3: return Brushes.Blue;
default: return DependencyProperty.UnsetValue;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
XAML
<UserControl.Resources>
<conv:ValueToBrushConverter x:Key="ValueToBrushConverter"/>
<Style x:Key="CellStyle" TargetType="DataGridCell">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource ValueToBrushConverter}}" />
</Style>
</UserControl.Resources>
<DataGrid x:Name="dataGrid" CellStyle="{StaticResource CellStyle}">
</DataGrid>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-12 17:10:12
Just put instead
<Style TargetType="{x:DataGridCell}" >
Ale uważaj, że będzie to skierowane do wszystkich komórek (celujesz we wszystkie obiekty typu DataGridCell
)
Jeśli chcesz umieścić styl zgodnie z typem komórki, polecam użycie DataTemplateSelector
Dobry przykład można znaleźć w samouczku DataGrid Christiana Mosersa:
Http://www.wpftutorial.net/DataGrid.html#rowDetails
Miłej zabawy:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-05 09:35:02
W moim przypadku konwerter musi zwracać wartość string. Nie wiem dlaczego, ale to działa.
*.xaml (common style file, który jest zawarty w innych plikach xaml)
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource ValueToBrushConverter}}" />
</Style>
*.cs
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Color color = VSColorTheme.GetThemedColor(EnvironmentColors.ToolWindowBackgroundColorKey);
return "#" + color.Name;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-29 20:04:33
To może Ci pomóc. Nie jest to jednak stock WPF datagrid.
Użyłem DevExpress z niestandardowym zachowaniem ColorFormatter. Nie mogłem znaleźć niczego na rynku, co zrobiłoby to po wyjęciu z pudełka. Zajęło mi to kilka dni, aby rozwinąć. Mój kod znajduje się poniżej, mam nadzieję, że to komuś pomoże.
Edit: używałem modeli widoku poco i MVVM, ale można to zmienić, aby nie używać POCO, jeśli pożądanie.
Viewmodel.cs
namespace ViewModel
{
[POCOViewModel]
public class Table2DViewModel
{
public ITable2DView Table2DView { get; set; }
public DataTable ItemsTable { get; set; }
public Table2DViewModel()
{
}
public Table2DViewModel(MainViewModel mainViewModel, ITable2DView table2DView) : base(mainViewModel)
{
Table2DView = table2DView;
CreateTable();
}
private void CreateTable()
{
var dt = new DataTable();
var xAxisStrings = new string[]{"X1","X2","X3"};
var yAxisStrings = new string[]{"Y1","Y2","Y3"};
//TODO determine your min, max number for your colours
var minValue = 0;
var maxValue = 100;
Table2DView.SetColorFormatter(minValue,maxValue, null);
//Add the columns
dt.Columns.Add(" ", typeof(string));
foreach (var x in xAxisStrings) dt.Columns.Add(x, typeof(double));
//Add all the values
double z = 0;
for (var y = 0; y < yAxisStrings.Length; y++)
{
var dr = dt.NewRow();
dr[" "] = yAxisStrings[y];
for (var x = 0; x < xAxisStrings.Length; x++)
{
//TODO put your actual values here!
dr[xAxisStrings[x]] = z++; //Add a random values
}
dt.Rows.Add(dr);
}
ItemsTable = dt;
}
public static Table2DViewModel Create(MainViewModel mainViewModel, ITable2DView table2DView)
{
var factory = ViewModelSource.Factory((MainViewModel mainVm, ITable2DView view) => new Table2DViewModel(mainVm, view));
return factory(mainViewModel, table2DView);
}
}
}
IView.cs
namespace Interfaces
{
public interface ITable2DView
{
void SetColorFormatter(float minValue, float maxValue, ColorScaleFormat colorScaleFormat);
}
}
Widok.xaml.cs
namespace View
{
public partial class Table2DView : ITable2DView
{
public Table2DView()
{
InitializeComponent();
}
static ColorScaleFormat defaultColorScaleFormat = new ColorScaleFormat
{
ColorMin = (Color)ColorConverter.ConvertFromString("#FFF8696B"),
ColorMiddle = (Color)ColorConverter.ConvertFromString("#FFFFEB84"),
ColorMax = (Color)ColorConverter.ConvertFromString("#FF63BE7B")
};
public void SetColorFormatter(float minValue, float maxValue, ColorScaleFormat colorScaleFormat = null)
{
if (colorScaleFormat == null) colorScaleFormat = defaultColorScaleFormat;
ConditionBehavior.MinValue = minValue;
ConditionBehavior.MaxValue = maxValue;
ConditionBehavior.ColorScaleFormat = colorScaleFormat;
}
}
}
DynamicConditionBehavior.cs
namespace Behaviors
{
public class DynamicConditionBehavior : Behavior<GridControl>
{
GridControl Grid => AssociatedObject;
protected override void OnAttached()
{
base.OnAttached();
Grid.ItemsSourceChanged += OnItemsSourceChanged;
}
protected override void OnDetaching()
{
Grid.ItemsSourceChanged -= OnItemsSourceChanged;
base.OnDetaching();
}
public ColorScaleFormat ColorScaleFormat { get; set;}
public float MinValue { get; set; }
public float MaxValue { get; set; }
private void OnItemsSourceChanged(object sender, EventArgs e)
{
var view = Grid.View as TableView;
if (view == null) return;
view.FormatConditions.Clear();
foreach (var col in Grid.Columns)
{
view.FormatConditions.Add(new ColorScaleFormatCondition
{
MinValue = MinValue,
MaxValue = MaxValue,
FieldName = col.FieldName,
Format = ColorScaleFormat,
});
}
}
}
}
Widok.xaml
<UserControl x:Class="View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
xmlns:ViewModels="clr-namespace:ViewModel"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:behaviors="clr-namespace:Behaviors"
xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
DataContext="{dxmvvm:ViewModelSource Type={x:Type ViewModels:ViewModel}}"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="{x:Type dxg:GridColumn}">
<Setter Property="Width" Value="50"/>
<Setter Property="HorizontalHeaderContentAlignment" Value="Center"/>
</Style>
<Style TargetType="{x:Type dxg:HeaderItemsControl}">
<Setter Property="FontWeight" Value="DemiBold"/>
</Style>
</UserControl.Resources>
<!--<dxmvvm:Interaction.Behaviors>
<dxmvvm:EventToCommand EventName="" Command="{Binding OnLoadedCommand}"/>
</dxmvvm:Interaction.Behaviors>-->
<dxg:GridControl ItemsSource="{Binding ItemsTable}"
AutoGenerateColumns="AddNew"
EnableSmartColumnsGeneration="True">
<dxmvvm:Interaction.Behaviors >
<behaviors:DynamicConditionBehavior x:Name="ConditionBehavior" />
</dxmvvm:Interaction.Behaviors>
<dxg:GridControl.View>
<dxg:TableView ShowGroupPanel="False"
AllowPerPixelScrolling="True"/>
</dxg:GridControl.View>
</dxg:GridControl>
</UserControl>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-19 00:35:16
// Example: Adding a converter to a column (C#)
Style styleReading = new Style(typeof(TextBlock));
Setter s = new Setter();
s.Property = TextBlock.ForegroundProperty;
Binding b = new Binding();
b.RelativeSource = RelativeSource.Self;
b.Path = new PropertyPath(TextBlock.TextProperty);
b.Converter = new ReadingForegroundSetter();
s.Value = b;
styleReading.Setters.Add(s);
col.ElementStyle = styleReading;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-27 09:34:15
Aby to zrobić w kodzie za (VB.NET)
Dim txtCol As New DataGridTextColumn
Dim style As New Style(GetType(TextBlock))
Dim tri As New Trigger With {.Property = TextBlock.TextProperty, .Value = "John"}
tri.Setters.Add(New Setter With {.Property = TextBlock.BackgroundProperty, .Value = Brushes.Green})
style.Triggers.Add(tri)
xtCol.ElementStyle = style
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-28 18:09:34