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

NestedStyleSelector implementation

2 Answers 50 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Art
Top achievements
Rank 1
Art asked on 02 Jun 2016, 07:37 AM

I hope that someone will find this as useful as it can be.

Purpose:

Can apply many StyleSelectors to one item by cascade.

public abstract class NestedStyleSelector : StyleSelector
{
    public StyleSelector ChildStyleSelector { get; set; }
 
    // Use this instead of the SelectStyle method
    //
    public abstract Style GetStyle(object item, DependencyObject container);
 
    public sealed override Style SelectStyle(object item, DependencyObject container)
    {
        Style currentStyle = GetStyle(item, container),
              childStyle = null;
 
        if (ChildStyleSelector != null)
        {
            childStyle = ChildStyleSelector.SelectStyle(item, container);
        }
 
        if (childStyle != null)
        {
            if (currentStyle != null && currentStyle.TargetType != childStyle.TargetType)
                throw new InvalidOperationException();
 
            var clonnedStyle = new Style(childStyle.TargetType)
            {
                BasedOn = currentStyle
            };
 
            foreach (var setterBase in childStyle.Setters)
            {
                var setter = setterBase as Setter;
 
                if (setter == null)
                    continue;
 
                clonnedStyle.Setters.Add(new Setter
                {
                    Property = setter.Property,
                    Value = setter.Value
                });
            }
 
            currentStyle = clonnedStyle;
        }
 
        return currentStyle ?? base.SelectStyle(item, container);
    }
}

 

Usage in child implementations:

<!-- Some class, that implements the NestedStyleSelector -->
<c:NestedStyleSelector>
    <c:NestedStyleSelector.ChildStyleSelector>
        <!-- Any another style selector -->
    </cNestedStyleSelector.ChildStyleSelector>
</c:NestedStyleSelector>

Restrictions:

- TargetType of all styles in chain must equals with it's parent returned style TargetType.

- Setter in choosen style of Child StyleSelector overrides the same property of parent style selector.

- BasedOn can be specified only in a first node declaration.

It works for me when I combine decisions, which row can be expanded and wich row has alternating background.

 

Sorry for my English :)

2 Answers, 1 is accepted

Sort by
0
Art
Top achievements
Rank 1
answered on 02 Jun 2016, 08:43 AM

There is strange issue, when setting currentStyle to childStyle (InvalidCastException). I've solved it by "clonning" the currentStyle too, before replacing it by childStyle:

public abstract class NestedStyleSelector : StyleSelector
{
    public StyleSelector ChildStyleSelector { get; set; }
 
    public abstract Style GetStyle(object item, DependencyObject container);
 
    public sealed override Style SelectStyle(object item, DependencyObject container)
    {
        Style currentStyle = CloneStyle(GetStyle(item, container)),
              childStyle = null;
 
        if (ChildStyleSelector != null)
        {
            childStyle = ChildStyleSelector.SelectStyle(item, container);
        }
 
        if (childStyle != null)
        {
            if (currentStyle != null && currentStyle.TargetType != childStyle.TargetType)
                throw new InvalidOperationException();
 
            childStyle = CloneStyle(childStyle);
            childStyle.BasedOn = currentStyle;
 
            currentStyle = childStyle;
        }
 
        return currentStyle ?? base.SelectStyle(item, container);
    }
 
    private static Style CloneStyle(Style sourceStyle)
    {
        if (sourceStyle == null)
            return null;
 
        var clonnedStyle = new Style(sourceStyle.TargetType)
        {
            BasedOn = sourceStyle.BasedOn
        };
 
        foreach (var setterBase in sourceStyle.Setters)
        {
            var setter = setterBase as Setter;
 
            if (setter == null)
                continue;
 
            clonnedStyle.Setters.Add(new Setter
            {
                Property = setter.Property,
                Value = setter.Value
            });
        }
 
        return clonnedStyle;
    }
}

0
Stefan
Telerik team
answered on 07 Jun 2016, 06:38 AM
Hello Artur,

Thank you for sharing this solution with the community. I have updated your Telerik points as a gratitude for your contribution.

All the best,
Stefan X1
Telerik
Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
Tags
GridView
Asked by
Art
Top achievements
Rank 1
Answers by
Art
Top achievements
Rank 1
Stefan
Telerik team
Share this question
or