Reputation: 55
Hi Guys: I am trying to style datagrid row. The flow is that based on a field in the grid (MsgType) I need to color the row. The color (both back and fore) is configurable by the user in the preferences screen and I save this configuration in an observable collection for each MsgType. The user can change this configuration through preferences screen. I need to bind the color (which can change) to the row for that MsgType. I have tried the following approach and the binding works only first time....since MsgType does not change. The color is fetched by the converter based on the msgtype.
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="{Binding MsgType, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource MessageTypeToBackConverter}}"/>
<Setter Property="Foreground" Value="{Binding MsgType, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource MessageTypeToForeConverter}}"/>
</Style>
</DataGrid.RowStyle>
Any help would be appreciated. I feel I might be taking the wrong approach.
Thanks,
Upvotes: 2
Views: 4769
Reputation: 19885
Well the behavior is working perfectly fine based on the your biding...
You have two options...
Keeping your code as it is, whenever preferences change, call DataGrid.Items.Refresh()
or rebind the DataGrid.ItemsSource
property to regenerate DataGridRows
. This way they will take the effect of the changed preferences (i.e. bg and fg colors would refresh).
The better way is to revamp your logic to use DynamicResources
based Brushes
to color the DataGridRows
via Triggers
assuming that MsgType
values are finite & well known at compile time ...
E.g.
Assuming that your MsgType
is some enum so it is well defined in terms of number of values it represents....
public enum MsgType
{
None = 0,
Read = 1,
Edit = 2,
Delete = 3
}
XAML
<DataGrid.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyDefaultPreferences.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</DataGrid.Resources>
...
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter property="BackgroundColor" Value="{DynamicResource NoneMsgTypeBrush}" />
<Style.Triggers>
<DataTrigger Binding="{Binding MsgType}" Value="1">
<Setter Property="BackgroundColor" Value="{DynamicResource ReadMsgTypeBrush}" />
</DataTrigger>
<DataTrigger Binding="{Binding MsgType}" Value="2">
<Setter Property="BackgroundColor" Value="{DynamicResource EditMsgTypeBrush}" />
</DataTrigger>
<DataTrigger Binding="{Binding MsgType}" Value="3">
<Setter Property="BackgroundColor" Value="{DynamicResource DeleteMsgTypeBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
MyDefaultPreferences.xaml
looks like below...
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<SolidColorBrush x:Key="NoneMsgTypeBrush" Color="White"/>
<SolidColorBrush x:Key="ReadMsgTypeBrush" Color="Gray"/>
<SolidColorBrush x:Key="EditMsgTypeBrush" Color="Green"/>
<SolidColorBrush x:Key="DeleteMsgTypeBrush" Color="Red"/> </ResourceDictionary>
So all you have to do at runtime, when user changes the preferences, just remove and add the Brushes
with same keys in MyDefaultPreferences.xaml
(its a Dictionary
)...
E.g.
If user changes Read Msg Type to be Yellow, all you have to do it this...
Uri uri = new Uri("MyDefaultPreferences.xaml", UriKind.RelativeOrAbsolute);
var _myDefaultResourceDictionary = Application.LoadComponent(uri) as ResourceDictionary;
_myDefaultResourceDictionary.Remove("ReadMsgTypeBrush");
_myDefaultResourceDictionary.Add("ReadMsgTypeBrush", new SolidColorBrush(Colors.Yellow));
This removal and addition of a Brush resource, changes the color wherever it is referred via DynamicResource
(i.e. in the corresponding SolidColorBrush
).
This is a very common way of changing skins \ themes of WPF applications at runtime.
Upvotes: 4