I am using silverlight Radgridview Q3 version .I have implemented a functionality called Color rules where depending on a cretain condition teh grid celles forground and background color should change.These conditions are set at runtime by user and not fixed so i cannot write a datatemplate in XAML.
Imagine user creates a rule where if the cell value is Yes then its background should be Green and If No then Red.
Now i have this rule which i need to apply to my grid. i tried writing a converter class something like this
public
class
BackColorConverter : IValueConverter
{
public
object
Convert(
object
value, Type targetType,
object
parameter, System.Globalization.CultureInfo culture)
{
ColorRuleConfig obj = parameter
as
ColorRuleConfig;
string
[] strarr = obj.RuleExpression.Split(
new
char
[]{
'='
});
string
strColName = strarr[0];
string
strColVal = strarr[1];
string
str = value
as
string
;
if
(String.IsNullOrEmpty(str))
{
return
string
.Empty;
}
try
{
if
(str == strColVal)
{
return
obj.RuleBackColor.ToString();
}
}
catch
{
}
return
str;
}
public
object
ConvertBack(
object
value, Type targetType,
object
parameter, System.Globalization.CultureInfo culture)
{
return
string
.Empty;
}
}
and i am applying my convertor like this
Dictionary<string, ColorRuleConfig> dictColorRuleConfig = viewmodelobj.dictColorRuleConfig;
if (dictColorRuleConfig != null && dictColorRuleConfig.Count > 0)
{
foreach (var item in dictColorRuleConfig)
{
GridViewColumn col = dataGrid1.Columns[item.Value.ColumnName];
Binding bindingForeColor = new Binding(item.Value.ColumnName.ToString()) { Mode = BindingMode.TwoWay, ConverterParameter = item.Value, Converter = (foreColorConvobj as IValueConverter) };
Binding bindingBackColor = new Binding(item.Value.ColumnName.ToString()) { Mode = BindingMode.TwoWay, ConverterParameter = item.Value, Converter = (backColorConvobj as IValueConverter) };
Style newstyle = new Style();
newstyle.TargetType =
typeof(GridViewCell);
Setter setterback = new Setter();
setterback.Property =
Button.BackgroundProperty;
setterback.Value = bindingBackColor;
Setter setterfore = new Setter();
setterfore.Property =
Button.ForegroundProperty;
setterfore.Value = bindingForeColor;
newstyle.Setters.Add(setterback);
newstyle.Setters.Add(setterfore);
col.CellStyle = newstyle;
}
}
But it is not applying my rules.Do you have any conditional formatting on grid column or any better way to achieve this.
10 Answers, 1 is accepted
In this very case I would advise you to use a RowStyleSelector. I have prepared an example project for you (I am attaching it to my post), where users can define a "Contains" condition and set foreground and background color for all the items that satisfy it. Please, refer to is and let us know if this approach fits into your requirements.
Regards,
Ivan Ivanov
the Telerik team
i want to add CellStyle selector. Instead of your row style selector. and i want to add it dynamically through code behind depending which column user has added rule. Can you tell me how this can be achieved
void ViewModel_delApplyRuleEvent()
{
Dictionary<string, ColorRuleConfig> dictColorRuleConfig = viewmodelobj.dictColorRuleConfig;
if (dictColorRuleConfig != null && dictColorRuleConfig.Count > 0)
{
foreach (var item in dictColorRuleConfig)
{
GridViewColumn col = dataGrid1.Columns[item.Value.ColumnName];
Color backcolor = new Color();
backcolor.A = 255;
backcolor.R = byte.Parse(item.Value.RuleBackColor.Substring(0, 2), NumberStyles.HexNumber);
backcolor.G = byte.Parse(item.Value.RuleBackColor.Substring(2, 2), NumberStyles.HexNumber);
backcolor.B = byte.Parse(item.Value.RuleBackColor.Substring(4, 2), NumberStyles.HexNumber);
SolidColorBrush BrushBackColor = new SolidColorBrush(backcolor);
Color forecolor = new Color();
forecolor.A = 255;
forecolor.R = byte.Parse(item.Value.RuleForeColor.Substring(0, 2), NumberStyles.HexNumber);
forecolor.G = byte.Parse(item.Value.RuleForeColor.Substring(2, 2), NumberStyles.HexNumber);
forecolor.B = byte.Parse(item.Value.RuleForeColor.Substring(4, 2), NumberStyles.HexNumber);
SolidColorBrush BrushForeColor = new SolidColorBrush(forecolor);
string[] strarr = item.Value.RuleExpression.Split(new char[] { '=' });
string strColName = strarr[0];
string strColVal = strarr[1];
Tuple<SolidColorBrush, SolidColorBrush> ColorsProperty = Tuple.Create<SolidColorBrush, SolidColorBrush>(BrushBackColor, BrushForeColor);
Func<string, bool> FuncProperty= (s) => { if (s == strColVal) return true; return false; };
Style st = new Style(typeof(GridViewCell));
st.Setters.Add(new Setter(GridViewCell.BackgroundProperty, ColorsProperty.Item1));
st.Setters.Add(new Setter(GridViewCell.ForegroundProperty, ColorsProperty.Item2));
this.Resources.Add(item.Value.ColumnName + "CellStyle", st);
StyleSelector sc = new StyleSelector();
//sc.SelectStyle(dataGrid1.Columns[item.Value.ColumnName],
dataGrid1.Columns[item.Value.ColumnName].CellStyleSelector = sc;
}
}
}
public class MyStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
Style st = new Style(typeof(GridViewCell));
st.Setters.Add(new Setter(GridViewCell.ForegroundProperty, SampleGrid.viewmodelobj.ColorsProperty.Item1));
st.Setters.Add(new Setter(GridViewCell.BackgroundProperty, SampleGrid.viewmodelobj.ColorsProperty.Item2));
return st;
}
}
I have modified my previous example project to work with CellStyleSelector. Please, have a look at it. I hope this solution meets your requirements.
Kind regards,
Ivan Ivanov
the Telerik team
in my case user may set different forgaroung and background colors so i may have multipe color rules each for different columns one column. In your code there is a fixed forground and background color and a fixed function which you set at once and apply to all columns. i cant do like that. depending upon the rules defined i need to create different style for each colum with its function and fore back color.So for every rule a seperate class simailar MyStyleSelector class needs to be created and its function property and color property needs to be set.Check my code below. i have a dictonary of rules for each colum(not necessary all columns). accordingly i pick each item and create style now now to dynamically add this style to style selector and apply it to column is hwere i am stuck up.
Dictionary<
string
, ColorRuleConfig> dictColorRuleConfig = viewmodelobj.dictColorRuleConfig;
if (dictColorRuleConfig != null && dictColorRuleConfig.Count > 0)
{
foreach (var item in dictColorRuleConfig)
{
GridViewColumn col = dataGrid1.Columns[item.Value.ColumnName];
Color backcolor = new Color();
backcolor.A = 255;
backcolor.R = byte.Parse(item.Value.RuleBackColor.Substring(0, 2), NumberStyles.HexNumber);
backcolor.G = byte.Parse(item.Value.RuleBackColor.Substring(2, 2), NumberStyles.HexNumber);
backcolor.B = byte.Parse(item.Value.RuleBackColor.Substring(4, 2), NumberStyles.HexNumber);
SolidColorBrush BrushBackColor = new SolidColorBrush(backcolor);
Color forecolor = new Color();
forecolor.A = 255;
forecolor.R = byte.Parse(item.Value.RuleForeColor.Substring(0, 2), NumberStyles.HexNumber);
forecolor.G = byte.Parse(item.Value.RuleForeColor.Substring(2, 2), NumberStyles.HexNumber);
forecolor.B = byte.Parse(item.Value.RuleForeColor.Substring(4, 2), NumberStyles.HexNumber);
SolidColorBrush BrushForeColor = new SolidColorBrush(forecolor);
string[] strarr = item.Value.RuleExpression.Split(new char[] { '=' });
string strColName = strarr[0];
string strColVal = strarr[1];
ColorsProperty = Tuple.Create<
SolidColorBrush
, SolidColorBrush>(BrushBackColor, BrushForeColor);
FuncProperty= (s) => { if (s == strColVal) return true; return false; };
Style st = new Style(typeof(GridViewCell));
st.Setters.Add(new Setter(GridViewCell.BackgroundProperty, ColorsProperty.Item1));
st.Setters.Add(new Setter(GridViewCell.ForegroundProperty, ColorsProperty.Item2));
this.Resources.Add(item.Value.ColumnName + "CellStyle", st);
StyleSelector sc = new StyleSelector();
sc.SelectStyle(dataGrid1.Columns[item.Value.ColumnName], st);*********************here i am stuck
dataGrid1.Columns[item.Value.ColumnName].CellStyleSelector = sc;
}
please let me know at the earliest.
public class MyStyleSelector : StyleSelector
{
public Tuple<
SolidColorBrush
, SolidColorBrush> ColorsProperty;
public Func<
string
, bool> FuncProperty;
public MyStyleSelector()
{
}
public MyStyleSelector(Tuple<
SolidColorBrush
, SolidColorBrush> ColorsProperty, Func<
string
, bool> FuncProperty)
{
this.ColorsProperty = ColorsProperty;
this.FuncProperty = FuncProperty;
}
public override Style SelectStyle(object item, DependencyObject container)
{
Style st = new Style(typeof(GridViewCell));
st.Setters.Add(new Setter(GridViewCell.ForegroundProperty, ColorsProperty.Item1));
st.Setters.Add(new Setter(GridViewCell.BackgroundProperty, ColorsProperty.Item2));
return st;
}
}
In order to prevent this overriding, you may add several style properties to your StyleSelector implementation. So when a condition is met, its respective style will be returned.
Best wishes,
Ivan Ivanov
the Telerik team
Can you modify your sample code to accept more than one conditions.
With the latest upgrade I can't get dynamic colors in CellStyleSelector to work anymore. So I was looking for an example to see what has changed, but I can't find anything more recent. The SilverlightApplication23 works initially, but it doesn't change the color when the user edits the cell value.
I modified the example to show what I need, but that gives wrong colors for cells. Is there a way to do this kind of dynamic cell coloring with the latest version of Telerik?
But for reproducing the issue, you can also use the original SilverlightApplication23 and do the following steps:
- set contains to the value of the first cell
- select a color, click apply
- Change the value of the first cell
- The color is still set, eventho it doesnt have a value that matches the contains text.
- Only when you click apply again will the color be removed.
Regards,
Bayram
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;
using System.Windows.Media;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
namespace SilverlightApplication23 {
public partial class MainPage : UserControl
{
public static MyViewModel vm = new MyViewModel();
public MainPage()
{
InitializeComponent();
LayoutRoot.DataContext = vm;
PropertiesBox.ItemsSource = typeof(Entry).GetProperties().ToList().Select(s => s.Name);
PropertiesBox.SelectedIndex = 0;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
vm.MatchText = containsTextBox.Text;
MainPage.vm.ColorsProperty = Tuple.Create<SolidColorBrush, SolidColorBrush>(new SolidColorBrush(ForegroundPicker.SelectedColor), new SolidColorBrush(BackgroundPicker.SelectedColor));
MainPage.vm.FuncProperty = (s) => { if (s.GetType().GetProperty(PropertiesBox.SelectedItem.ToString()).GetValue(s, null).ToString().Contains(containsTextBox.Text)) return true; return false; };
foreach(var c in testGrid.Columns)
(c as GridViewDataColumn).CellStyleSelector = new MyStyleSelector();
testGrid.Rebind();
}
}
public class MyStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
GridViewCell cell = (GridViewCell)container;
if (cell.Value != null)
{
string text = (string)cell.Value;
if (text.Contains(MainPage.vm.MatchText))
{
Style st = new Style(typeof(GridViewCell));
st.Setters.Add(new Setter(GridViewRow.ForegroundProperty, MainPage.vm.ColorsProperty.Item1));
st.Setters.Add(new Setter(GridViewRow.BackgroundProperty, MainPage.vm.ColorsProperty.Item2));
return st;
}
else
return null;
}
else
return null;
}
}
public class Entry
{
public string EntryLabel1 { get; set; }
public string EntryLabel2 { get; set; }
}
public class MyViewModel
{
public ObservableCollection<Entry> LabelProperty { get; set; }
public Tuple<SolidColorBrush, SolidColorBrush> ColorsProperty { get; set; }
public Func<Entry, bool> FuncProperty { get; set; }
public string MatchText { get; set; }
public MyViewModel()
{
LabelProperty = new ObservableCollection<Entry>();
Random rnd = new Random();
for (int i = 0; i < 100; i++)
{
LabelProperty.Add(new Entry() { EntryLabel1 = rnd.Next().ToString(), EntryLabel2 = rnd.Next().ToString() });
}
}
}
}
I found out what the problem is with my source, you can no longer use cell.Value, it doesn't always correspond to the actual cell value.
A workaround (or actually maybe this is a better solution) is to get the value of the property of the underlying business object (the first parameter of SelectStyle). The easiest way to achieve that is to have a different style selector for each column you want to color dynamically, then you always know which property you have to get the value of.
Regards,
Bayram