Severity is an enum type. The below XAML doesn't work. If I compare on another property of Int type, the styles are selected just fine. I also tried to compare against the underlying constant value, but no cigar. Can I use the conditionalstyleselector on an Enum type?
<telerik:RadGridView ItemsSource="{Binding IssuesFound}">
<telerik:RadGridView.RowStyleSelector>
<telerik:ConditionalStyleSelector>
<telerik:StyleRule Condition="Severity = Error">
<Style TargetType="telerik:GridViewRow">
<Setter Property="Background" Value="Red"/>
</Style>
</telerik:StyleRule>
<telerik:StyleRule Condition="Severity = Warning">
<Style TargetType="telerik:GridViewRow">
<Setter Property="Background" Value="Yellow"/>
</Style>
</telerik:StyleRule>
<telerik:StyleRule Condition="Severity = Information">
<Style TargetType="telerik:GridViewRow">
<Setter Property="Background" Value="Blue"/>
</Style>
</telerik:StyleRule>
</telerik:ConditionalStyleSelector>
</telerik:RadGridView.RowStyleSelector>
</telerik:RadGridView>
9 Answers, 1 is accepted
The conditional style selector does not implement logic to parse enum from string in its expression the way you expect.
Therefore I may recommend switching to a regular style selector and do the comparison logic in the SelectStyle Method.
All the best,
Pavel Pavlov
the Telerik team
I want to group the rows of data according to their values. For exemple, if 3 lines of data have the same ID, i will group them if not i will do nothing.
I have found a exemple like this :
<telerik:RadGridView.RowStyleSelector>
<telerik:ConditionalStyleSelector>
<telerik:StyleRule Condition="ShipCountry = 'France'">
<Style TargetType="telerik:GridViewRow">
<Setter Property="IsExpandable" Value="True" />
</Style>
</telerik:StyleRule>
</telerik:ConditionalStyleSelector>
</telerik:RadGridView.RowStyleSelector>
How can i replace the fixed value here "France " with a variable so that i can regoup the lines of data which have the same ID ?
Please clarify , do you need grouping or just conditional colorizing ?
Kind regards,
Pavel Pavlov
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
I have the same problem. I need grouping where data has the same id.
It's possible?
Hi
So ive noticed same behaivour in latest release
Ive tried various combinations, for example:
// In resource library
<
telerik:ConditionalStyleSelector
x:Key
=
"CellStyleSelecter_XStatus"
>
<
telerik:StyleRule
Condition
=
"LicenceStatus= LicenceStatus.Active"
>
<
Style
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Status_Active}"
/>
</
telerik:StyleRule
>
<
telerik:StyleRule
Condition
=
"LicenceStatus != LicenceStatus.Active"
>
<
Style
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Status_Inactive}"
/>
</
telerik:StyleRule
>
</
telerik:ConditionalStyleSelector
>
<
telerik:ConditionalStyleSelector
x:Key
=
"CellStyleSelecter_Licences_LicenceStatus"
>
<
telerik:StyleRule
Condition
=
"LicenceExpires < DateTime.Now() AND LicenceStatus != 'Expired'"
>
<
Style
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Status_Error}"
/>
</
telerik:StyleRule
>
<
telerik:StyleRule
Condition
=
"LicenceStatus = 'Active'"
>
<
Style
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Status_Active}"
/>
</
telerik:StyleRule
>
<
telerik:StyleRule
Condition
=
"LicenceStatus = 'Expired' || LicenceStatus = 'Deactivated'"
>
<
Style
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Status_Inactive}"
/>
</
telerik:StyleRule
>
</
telerik:ConditionalStyleSelector
>
// In view
<telerik:GridViewDataColumn DataMemberBinding="{Binding LicenceStatus}" Header="Status" CellStyleSelector="{StaticResource CellStyleSelecter_Licences_LicenceStatus}"/>
But im not seeing anything work.
I looked at examples in the demos and made a conditionalstyleselecter override and ect, but i have just too many conditions and styles to effectivly apply there, and i couldnt get Expressions to work the way i wanted.
Here is a copy of my last version of core CellStyleSelector file before i stopped that approach
public
class
CellStyleSelector : StyleSelector
{
// public Dictionary<String, Dictionary<string, Style>> conditions { get; set; }
// Use a Dictionary mapping ColumnName to a List of ConditionalStyleRule
Dictionary<
string
, List<CellStyleRule>> _Rules;
public
Dictionary<
string
, List<CellStyleRule>> Rules
{
get
{
if
(
this
._Rules ==
null
)
{
this
._Rules =
new
Dictionary<
string
, List<CellStyleRule>>();
}
return
this
._Rules;
}
set
{
this
._Rules = value; }
}
public
override
Style SelectStyle(
object
item, DependencyObject container)
{
if
(item
is
BaseDataModel)
{
GridViewCell cell = container
as
GridViewCell;
var currentColumn = cell.Column
as
GridViewDataColumn;
string
key = currentColumn.DataMemberBinding.Path.Path;
if
(Rules.ContainsKey(key))
{
foreach
(CellStyleRule rule
in
Rules[key])
{
// Error line, not sure how to apply an expression
if
(((BaseDataModel)item).Where (rule.Condition))
{
return
rule.Style;
}
}
}
}
return
null
;
}
}
/// <summary>
/// ConditionalStyleRule is used in CellStyleSelector and its inheriting classes.
///
/// Wouldnt be too hard to modify to allow declarative if highly desired.
///
/// NOTE - tried extending telerik.StyleRule, issues with setting condition value
/// </summary>
public
class
CellStyleRule
{
/*
object _Value;
public object Value
{
get
{
return this._Value;
}
set
{
this._Value = value;
}
}
*/
// NOTE - if needing to widen use case, use <T>, but ONLY if needed
Expression<Func<BaseDataModel,
bool
>> _Condition;
public
Expression<Func<BaseDataModel,
bool
>> Condition
{
get
{
return
this
._Condition;
}
set
{
this
._Condition = value;
}
}
Style _Style;
public
Style Style
{
get
{
return
this
._Style;
}
set
{
this
._Style = value;
}
}
public
CellStyleRule(Expression<Func<BaseDataModel,
bool
>> c,
string
s)
{
var d = App.Current.FindResource(s);
if
(d !=
null
)
Style = d
as
Style;
else
throw
new
Exception(
"No such style resource as '"
+ s +
"'"
);
// Value = v;
Condition = c;
}
/*
public CellStyleRule(string c, string s)
{
var d = App.Current.FindResource(s);
if (d != null)
Style = d as Style;
else
throw new Exception("No such style resource as '" + s + "'");
// TODO - test - guessing at how to do this based on telerik classes
// Value = v;
Telerik.Windows.Data.ExpressionTypeConverter converter = new Telerik.Windows.Data.ExpressionTypeConverter();
Condition = (System.Linq.Expressions.Expression) converter.ConvertFromString(c);
c.ToString();
}
*/
}
I used that by creating inheriting classes that set the value of this.Rules in constructor, then used them as static resource where needed.
The Dictionary wrap was to help simplify management as the tables centered around a core collection of BaseDataModel classes
My problem with this approach is i couldnt get Expressions (item.Where) to work as couldnt find working example of Expressions or LambdaExpressions or delegate or anything without a IEnumerable
So i quickly did up a working version that handles JUST simple enum checks, tested just on licences but works fine
Note this does NOT solve my issue as i cant perform any of the other logic checks as shown in my previous post, nor compound conditions or any other use case except simple IF(this == that)
But as this does handle enums maybe it helps others, though the code really should nativle
// NOTE - abstract as i havent done anything to define declarative behaivour, wouldnt be hard to work in though
public
abstract
class
EnumCellStyleSelector<T> : StyleSelector
{
public
Dictionary<
string
,
string
> Styles {
set
;
get
; }
public
string
PropertyName {
set
;
get
; }
public
override
Style SelectStyle(
object
item, DependencyObject container)
{
if
(item
is
BaseDataModel)
{
BaseDataModel obj = item
as
BaseDataModel;
foreach
(
string
keystring
in
this
.Styles.Keys)
{
string
[] keys = keystring.Split(
','
);
foreach
(
string
k
in
keys)
{
// NOTE - i use my helper function to retrieve property name, but many solutions exist for this
var val = GeneralUtil.GetPropValue(obj,
this
.PropertyName);
if
(val !=
null
)
{
if
(k.Trim() == val.ToString().Trim())
{
var d = App.Current.FindResource(
this
.Styles[k]);
if
(d !=
null
)
return
d
as
Style;
else
throw
new
Exception(
"No such style resource as '"
+
this
.Styles[k] +
"'"
);
}
}
else
{
throw
new
Exception(
"No such property '"
+
this
.PropertyName +
"'"
);
}
}
}
}
return
base
.SelectStyle(item, container);
}
}
public
class
LicenceStatusCellStyleSelector : EnumCellStyleSelector<BaseDataModel>
{
public
LicenceStatusCellStyleSelector()
:
base
()
{
this
.PropertyName =
"LicenceStatus"
;
this
.Styles =
new
Dictionary<
string
,
string
>()
{
{
"Expired, Deactivated"
,
"CellStyle_Status_Inactive"
},
{
"Active"
,
"CellStyle_Status_Active"
},
};
}
}
<
telerik:RadGridView.Resources
>
<
gridviewstyleselectors:LicenceStatusCellStyleSelector
x:Key
=
"LicenceStatusCellStyleSelector"
/>
</
telerik:RadGridView.Resources
>
...
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding LicenceStatus}"
Header
=
"Status"
CellStyleSelector
=
"{StaticResource LicenceStatusCellStyleSelector}"
/>
This is only a simple workaround, does not solve this issue at hand but maybe helps someone
Can i please still get a reply to my previous post
So i looked again and moved away from linq, looked more at the Func<obj,bool>
I have a semi-functioning version, gota go but will post it once i work out kinks
So here is a working implementation of a ConditonalStyleSelector type approach that I have made semi modular
There is no code to handle declarative binding (xaml), but wouldnt be hard to mix in by looking at the Telerik Demo suites as they implement similar with declarative
I personally prefer to use classes and direct assignment, but i can see the appeal for the other approach.
public
class
CellStyleSelector : StyleSelector
{
// Use a Dictionary mapping X columns to individual Lists of rules to check
Dictionary<
string
, List<CellStyleRule>> _Rules;
public
Dictionary<
string
, List<CellStyleRule>> Rules
{
get
{
if
(
this
._Rules ==
null
)
{
this
._Rules =
new
Dictionary<
string
, List<CellStyleRule>>();
}
return
this
._Rules;
}
set
{
this
._Rules = value; }
}
public
override
Style SelectStyle(
object
item, DependencyObject container)
{
if
(item
is
BaseDataModel)
{
GridViewCell cell = container
as
GridViewCell;
var currentColumn = cell.Column
as
GridViewDataColumn;
string
key = currentColumn.DataMemberBinding.Path.Path;
if
(Rules.ContainsKey(key))
{
foreach
(CellStyleRule rule
in
Rules[key])
{
// string debug = DebugHelper.Debug(rule.Condition);
// REVERTED NOTE - if just Func<>
// if (rule.Condition((BaseDataModel)item))
// NOTE - if Expression<Func<>>, first compile then pass in param
if
(rule.Condition.Compile()((BaseDataModel)item))
{
return
rule.Style;
}
}
}
}
return
null
;
}
}
/// <summary>
/// Used in CellStyleSelector and its inheriting classes.
///
/// Wouldnt be too hard to modify to allow declarative if highly desired.
///
/// NOTE - tried extending telerik.StyleRule, issues with setting condition value
/// </summary>
public
class
CellStyleRule
{
Expression<Func<BaseDataModel,
bool
>> _Condition;
public
Expression<Func<BaseDataModel,
bool
>> Condition
{
get
{
return
this
._Condition;
}
set
{
this
._Condition = value;
}
}
Style _Style;
public
Style Style
{
get
{
return
this
._Style;
}
set
{
this
._Style = value;
}
}
public
CellStyleRule(Expression<Func<BaseDataModel,
bool
>> c,
string
s)
{
var d = App.Current.FindResource(s);
if
(d !=
null
)
this
.Style = d
as
Style;
else
throw
new
Exception(
"No such style resource as '"
+ s +
"'"
);
// Value = v;
Condition = c;
}
}
public
class
LicenceTableCellStyleSelector : CellStyleSelector
{
public
LicenceTableCellStyleSelector()
:
base
()
{
this
.Rules =
new
Dictionary<
string
, List<CellStyleRule>>()
{
{
"LicenceStatus"
,
new
List<CellStyleRule>()
{
// Always most specific rules at top
// Error catcher, leave in as visual cue just in case
{
new
CellStyleRule(x => ((Licence)x).LicenceExpires < DateTime.Now && ((Licence)x).LicenceStatus != LicenceStatus.Expired,
"CellStyle_Licence_ExpiryMismatch"
) } ,
{
new
CellStyleRule(x => ((Licence)x).LicenceStatus == LicenceStatus.Active,
"CellStyle_Status_Active"
) } ,
// Same as != Active, as only those would through this far
{
new
CellStyleRule(x => x !=
null
,
"CellStyle_Status_Inactive"
) } ,
}
},
{
"LicenceType"
,
new
List<CellStyleRule>()
{
{
new
CellStyleRule(x => ((Licence)x).LicenceType == LicenceType.Full,
"CellStyle_Licence_Full"
) } ,
{
new
CellStyleRule(x => ((Licence)x).LicenceType == LicenceType.Upgrade,
"CellStyle_Licence_Upgrade"
) } ,
// Timed, uses fallthrough so no need to actually check unless wanting to distinct types of timed
{
new
CellStyleRule(x => x !=
null
,
"CellStyle_Status_Active"
) } ,
}
},
{
"LicenceExpired"
,
new
List<CellStyleRule>()
{
{
new
CellStyleRule(x => ((Licence)x).LicenceExpires < DateTime.Now && ((Licence)x).LicenceStatus != LicenceStatus.Expired,
"CellStyle_Licence_ExpiryMismatch"
) },
{
new
CellStyleRule(x => ((Licence)x).LicenceExpires < ((Licence)x).LicenceIssued,
"CellStyle_Licence_ExpiryMismatch"
) } ,
}
},
{
"LicenceIssued"
,
new
List<CellStyleRule>()
{
{
new
CellStyleRule(x => ((Licence)x).LicenceExpires < ((Licence)x).LicenceIssued,
"CellStyle_Licence_ExpiryMismatch"
) } ,
}
}
};
}
}
<!--
The following are styles applied to cells or rows in RadGridViews based on StyleSelectors
First is generic colours, which are inherited by semi-generic flag styles, which optionally
can be further inherited by table-specific styles (which can include tooltips and other properties)
As a general rule, no colour style is applied directly, instead using semi-generic or table-specific
styles so as to make changes easier to manage. Which style actually matches which condition is
entirely the responsibility of the StyleSelector.
<
Style
x:Key
=
"CellStyle_"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
""
/>
</
Style
>
-->
<
Style
x:Key
=
"CellStyle_Green"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"Green"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_DarkGreen"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"DarkGreen"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_ExtraDarkGreen"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"#004000"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_MediumBlue"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"MediumBlue"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_DarkBlue"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"DarkBlue"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_Purple"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"Purple"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_Red"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"Red"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_Crimson"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"Crimson"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_DarkOrange"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"DarkOrange"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_Silver"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"Silver"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_DarkGray"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"DarkGray"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_Gray"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource GridViewCellStyle}"
>
<
Setter
Property
=
"Foreground"
Value
=
"Gray"
/>
</
Style
>
<
Style
x:Key
=
"CellStyle_Muted"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Gray}"
/>
<
Style
x:Key
=
"CellStyle_Status_Active"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_ExtraDarkGreen}"
/>
<
Style
x:Key
=
"CellStyle_Status_Inactive"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Gray}"
/>
<
Style
x:Key
=
"CellStyle_Status_Warning"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Crimson}"
/>
<
Style
x:Key
=
"CellStyle_Status_Error"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Red}"
/>
<
Style
x:Key
=
"CellStyle_Licence_Full"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_DarkBlue}"
/>
<
Style
x:Key
=
"CellStyle_Licence_Upgrade"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Purple}"
/>
<
Style
x:Key
=
"CellStyle_Licence_ExpiryMismatch"
TargetType
=
"telerik:GridViewCell"
BasedOn
=
"{StaticResource CellStyle_Status_Error}"
>
<
Setter
Property
=
"ToolTip"
Value
=
"Expiry doesnt match Status or Issued Date"
/>
</
Style
>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding LicenceType}"
Header
=
"Licence Type"
/>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding LicenceIssued}"
Header
=
"Issued"
CellStyleSelector
=
"{StaticResource LicenceTableCellStyleSelector}"
/>
<
telerik:GridViewDataColumn
DataMemberBinding
=
"{Binding LicenceExpires}"
Header
=
"Expiry"
CellStyleSelector
=
"{StaticResource LicenceTableCellStyleSelector}"
/>
​Thank you so much for sharing the working implementation you came up with.
In case you still have any pending not-resolved questions, may I ask you to isolate the issue in a demo project and send it to us via a support ticket. That way we can debug it at our side and advice further.
Regards,
Dimitrina
Telerik