This is a migrated thread and some comments may be shown as answers.

Conditional formatting in Grid

10 Answers 354 Views
GridView
This is a migrated thread and some comments may be shown as answers.
preeti
Top achievements
Rank 1
preeti asked on 14 Mar 2011, 09:12 AM
Hi,

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

Sort by
0
Ivan Ivanov
Telerik team
answered on 14 Mar 2011, 12:46 PM
Hi preeti,

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
Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
0
preeti
Top achievements
Rank 1
answered on 15 Mar 2011, 09:56 AM
Hi ,

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;
        }
    }
0
Ivan Ivanov
Telerik team
answered on 15 Mar 2011, 02:11 PM
Hello preeti,

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
Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
0
preeti
Top achievements
Rank 1
answered on 16 Mar 2011, 09:09 AM
i have made thse changes in style code that i had pasted above.
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.
0
preeti
Top achievements
Rank 1
answered on 16 Mar 2011, 09:25 AM
Hi i solved the poblem by passing my color values to the Mystyleselector class.Thankyou
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;
       }
   }
0
preeti
Top achievements
Rank 1
answered on 16 Mar 2011, 10:22 AM
I am facing problem when there are two conditions defined for a single column. I have a column hwere if the cell value is "Y" the the cell sould have a different fore and back color and if value is "N" then a different fore and back color .by applying the CellstyleSelector to column the later rule is overiting the previous one. I think i need to use a rowstyle selector but how do i apply to each row dynamically. Please help.
0
Ivan Ivanov
Telerik team
answered on 16 Mar 2011, 02:17 PM
Hi preeti,

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
Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
0
preeti
Top achievements
Rank 1
answered on 17 Mar 2011, 09:47 AM
I am not able to achieve this even after changeing conditions.
Can you  modify your sample code to accept more than one conditions.
0
B
Top achievements
Rank 2
answered on 05 Jul 2012, 09:10 AM
Hi Ivan

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:
  1.  set contains to the value of the first cell
  2. select a color, click apply
  3. Change the value of the first cell
  4. The color is still set, eventho it doesnt have a value that matches the contains text.
  5. 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<SolidColorBrushSolidColorBrush>(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 truereturn 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 { getset; }
        public string EntryLabel2 { getset; }
    }
    public class MyViewModel
    {
        public ObservableCollection<Entry> LabelProperty { getset; }
        public Tuple<SolidColorBrushSolidColorBrush> ColorsProperty { getset; }
        public Func<Entrybool> FuncProperty { getset; }
        public string MatchText { getset; }
        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() });
            }
        }
    }
}

0
B
Top achievements
Rank 2
answered on 05 Jul 2012, 03:40 PM
Hi,

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
Tags
GridView
Asked by
preeti
Top achievements
Rank 1
Answers by
Ivan Ivanov
Telerik team
preeti
Top achievements
Rank 1
B
Top achievements
Rank 2
Share this question
or