WPF - Binding multiple values to a datagrind
UPDATED : Clean subject, and summarize it.
Hi, I've a datable fill开发者_StackOverflow中文版ed, where each cell is a class like this
class CValue{
public object Value;
public Brush Quality;
private int m_quality;
public override String toString(){
return Value.toString();
}
}
My datagrid is bind on the datable, and it's working well. But my aim is to switch the background color of the cell depending of the Quality value.
I intend tu use datatemplate but don't know how it's working at all...
<dg:DataGrid Name="DataGridResult" IsReadOnly="True" AutoGenerateColumns="False"
BorderThickness="1" BorderBrush="{DynamicResource clBLACK}"
CanUserReorderColumns="False"
ItemsSource="{Binding Path=Result}">
<dg:DataGrid.Resources>
<Style TargetType="{x:Type dg:DataGridCell}">
<Style.Setters>
<Setter Property="Background" Value="{Binding [1].Quality}"/>
</Style.Setters>
</Style>
</dg:DataGrid.Resources>
<dg:DataGrid.ItemTemplate>
<DataTemplate>
<dg:DataGridCell>
</dg:DataGridCell>
</DataTemplate>
</dg:DataGrid.ItemTemplate>
</dg:DataGrid>
Actually, if the Value of the background's setter is set to "Blue", all cells are blued, so it's fine, but I can't find a way to bind it to my property. the [1] seems to return the column 1 of the row...
How to set to the cell dynamically ? 'Cause i've got a dynamic number of columns but there all of the CValue Type.
Ok. So for an entire example databinding to the Brush of the model instead of using converters, styles etc. For the following cs -code:
class CValue
{
public string Value { get; set; } // Notice we use properties for binding and not fields
public Brush Quality { get; set; } // Notice we use properties for binding and not fields
private int m_quality;
public override String ToString()
{
return Value.ToString();
}
}
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
// Databind the list
myGrid.ItemsSource = new List<CValue>
{
new CValue
{
Value = "First",
Quality = new SolidColorBrush(Color.FromArgb(255, 0, 255, 255))},
new CValue
{
Value = "Second",
Quality = new SolidColorBrush(Color.FromArgb(255, 255, 0, 255))
},
new CValue
{
Value = "Third",
Quality = new SolidColorBrush(Color.FromArgb(0, 255, 255, 255))
}
};
}
}
You would use a xaml for the rowstyle (notice the TargetType
on the style and the AutoGenerateColumns="false"
) to bind the row-color and the value:
<Controls:DataGrid x:Name="myGrid" AutoGenerateColumns="False">
<Controls:DataGrid.RowStyle>
<Style TargetType="{x:Type Controls:DataGridRow}">
<Setter Property="Background" Value="{Binding Quality}" />
</Style>
</Controls:DataGrid.RowStyle>
<Controls:DataGrid.Columns>
<Controls:DataGridTemplateColumn Header="Value">
<Controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Value}" />
</DataTemplate>
</Controls:DataGridTemplateColumn.CellTemplate>
</Controls:DataGridTemplateColumn>
</Controls:DataGrid.Columns>
</Controls:DataGrid>
Hope it helps!
One good way of doing this which keeps the coloring visible in the XAML is to use a style with binding to the quality. We put this style in the some resourcedictionary above the template, like in my case in the DataGrid.Resources.
<Controls:DataGrid>
<Controls:DataGrid.Resources>
<Style TargetType="{x:Type Controls:DataGridCell}">
<Style.Triggers>
<DataTrigger Binding="{Binding Quality}" Value="0">
<Setter Property="Background" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding Quality}" Value="0">
<Setter Property="Background" Value="Blue" />
</DataTrigger>
</Style.Triggers>
</Style>
</Controls:DataGrid.Resources>
<Controls:DataGrid.ItemTemplate>
<DataTemplate>
<Controls:DataGridCell>
</Controls:DataGridCell>
</DataTemplate>
</Controls:DataGrid.ItemTemplate>
</Controls:DataGrid>
Update:
To be able to databind the values or whatever use a converter like this:
[ValueConversion(typeof(int), typeof(SolidColorBrush))]
public class QualityToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// Cast value
int intValue = (int) value;
if (intValue == 1)
return new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
return new SolidColorBrush(Color.FromArgb(255, 0, 0, 255));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException("TwoWay binding not supported!");
}
}
Bind it in the XAML like the follwing:
<Window.Resources>
<WpfApplication1:QualityToColorConverter x:Key="ColorConverter" />
</Window.Resources>
<Controls:DataGridCell Background="{Binding Quality, Converter={StaticResource ColorConverter}}">
</Controls:DataGridCell>
You should use DataTemplateSelector
class to perform this logic.
The scenario is described below:
- Create the set of DataTemplates;
- Derive from DataTemplateSelector Class and implement there logic of selecting appropriate
DataTemplate
as described in MSDN Article; - Define your custom
DataTemplateSelector
as the resource specifying thex:Key
attribute; - Bind needed object to defined
DataTemplateSelector
resource.
UPDATE
The upper approach works best when you need to completely redesign cells as the guys mentioned in comment.
So for this task you should create your converter, define it as a resource and add it to your binding:
<!--somewhere in resources-->
<QualityToBackgroundConverter x:Key="qualityToBackgroundConverter "/>
then binding will look like:
Background="{Binding Quality, Converter={StaticResource qualityToBackgroundConverter }}"
and finally the converter:
[ValueConversion(typeof(Quality), typeof(Brush))]
public class QualityToBackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
Quality quality = (Quality)value;
switch (quality)
{
case 0: return Brushes.Red;
case 1: return Brushes.Yellow;
case 2: return Brushes.Green;
default: return Brushes.Transparent;
}
}
return Brushes.Transparent;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw NotImplementedException();
}
}
精彩评论