Skip to main content

Microsoft Silverlight

Answered Question ImplicitStyleManager Propogate Correclty?RSS Feed

(0)

ld1453
ld1453

Member

Member

284 points

112 Posts

ImplicitStyleManager Propogate Correclty?

[EDIT: Clarified my question below]

ld1453
ld1453

Member

Member

284 points

112 Posts

Re: ISM TraverseDepthFirst Implementation

Maybe a better question is "Why does ImplicitStyleManager iterate over elements that it is changing?"

Every iteration of the foreach loop in ImplicitStyleManager.PropagateStyles() could apply a style to an element, and in doing so, could change the remaining enumeration. I'm sorry if that's not so clear.

Why not  place the Tuples inside IEnumberable elementsToStyleAndDictionaries inside a fixed storage, like a List, and then loop though them setting the styles?

Jonathan Shen – MSFT
Jonathan...

All-Star

All-Star

24939 points

2,425 Posts

Microsoft

Re: ISM TraverseDepthFirst Implementation

Hi Ld1453,

Actually, as far as I know, PropagateStyles is not supported on Silverlight 2.  If you want to apply style to controls, please reference to these articles.

http://themechanicalbride.blogspot.com/2008/11/using-implicitstylemanager-and-theme.html

http://www.nikhilk.net/Silverlight-Themes.aspx

Best regards,

Jonathan

Jonathan Shen
Microsoft Online Community Support
Please remember to mark the replies as answers if they help and unmark them if they provide no help.

ld1453
ld1453

Member

Member

284 points

112 Posts

Re: ISM TraverseDepthFirst Implementation

 Hmmm... I think we may be talking about different things.  I meant the PropagateStyles priviate method defined in the class ImplicitStyleManager.

But either way, you were correct in that itdoesn't work and my question is why it was made to not work. The way it is defined now the items the enumerator would return in the foreach loop can and do change as styles are applied. And since it is a DepthFirst approach setting a style on a parent could stop a child from being styled properly. My question is, was it made that way on purpose?

I've changed it in my local copy to enumerate the entire tree before any styles are applied (by creating a List<FrameworkElement>) and then start applying styles. I've yet to see any ill effects but I assume the people who wrote it know more than I do so I thought I'd ask the community here.

Thanks for the response, Jonathan.

jahusain
jahusain

Member

Member

342 points

52 Posts

Re: ISM TraverseDepthFirst Implementation

If I'm understanding you correctly you are saying that applying a style to a parent in the sequence of FrameworkElements might cause a child to disappear.  You are indeed correct and it would likely be best if we took a copy of the stream into a list.  Out of curiousity did you experience an exception?  If so, what was it? 

Thanks,

Jafar

ld1453
ld1453

Member

Member

284 points

112 Posts

Re: ISM TraverseDepthFirst Implementation

That's correct, applying a style to a parent makes a child disappear, or more precisely, VisualTreeHelper.GetChild() no longer can no longer returns them. There aren't any exceptions, chlidren just don't get styled.

Here's a very simple example (I uploaded the project here): 

    <Grid  x:Name="LayoutRoot" theme:ImplicitStyleManager.ApplyMode="OneTime" theme:ImplicitStyleManager.ResourceDictionaryUri="themes/Classic.xaml">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Button x:Name="Button1" Content="Styled Button" />
        <ScrollViewer x:Name="ScrollViewer1" Grid.Row="1">
            <Button x:Name="Button2" Content="Unstyled Button" />
        </ScrollViewer>
    </Grid>

If you set a breakpoint at Line 552 at the foreach loop of ImplicitStyleManger.PropagateStyles() you can ask for elementsToStyleAndDictionaries to be enumerated.  As you might expect, it lists all the elements as defined in XAML. 

As it continues ISM goes through styling first LayoutRoot, then Button1, then ScrollViewer1. Then the next in the next iteration the enumerator cannot find any children for ScrollViewer1 even though it very clearly found it before the a style was applied to ScrollViewer1. If you instruct the debugger to skip the statement applying the style for ScrollViewer1, Button2 is again found and styled correctly. I'm not sure what happens to cause VisualTreeHelper to not see the children anymore but it happens.

So we're in agreement it's best to take a copy of the elements before applying the styles? You don't see any major problems with it? If so, I'll open up an Issue on their tracker.

jahusain
jahusain

Member

Member

342 points

52 Posts

Re: ISM TraverseDepthFirst Implementation

Before you log an issue I'd like to know what style you apply to scrollviewer.  Does that style change the content property, thereby removing children or do anything else that might cause the children to disappear.  Also which version of Silverlight are you using?  Can you send a small repro?   

Thanks very much,

Jafar

ld1453
ld1453

Member

Member

284 points

112 Posts

Re: ISM TraverseDepthFirst Implementation

Ah, you're good. I'm understanding the problem much better.  The style applied to the ScrollViewer doesn't change the content directly, but it does redefine the Template.  If I'm correct, the reason ISM isn't finding any children for the ScrollViewer is because it doesn't have any!  In applying the new template it also gets a new ScrollContentPresenter whose Content won't be assigned until the next ApplyTemplate call.

This can be fixed by setting the ISM ApplyMode to Auto so that when the Content is assigned and a LayoutUpdated event produced, ISM will come back and style the Content correctly. I'm not sure that's the best approach though because all the other things I've read say that the overhead for ApplyMode=Auto is considerable and it can can also be fixed using the suggestion stated before.  What do you think?

I'm not sure if this has anything to do with having to use ApplyMode=Auto on ItemsControl but I'll take a look at it tomorrow morning and update this.

Here's the project. I'm still using Silverlight 2.

jahusain
jahusain

Member

Member

342 points

52 Posts

Answered Question

Re: ISM TraverseDepthFirst Implementation

Yeah under the circumstances the gradual drill-down behavior of ISM is correct.  Apply the style to a parent may change its children.  In this case by lazily evaluating the stream of children is best so that we get the new children instead of the old cached one.

It's almost always a good idea to avoid Auto and just manually apply the style using ImplicitStyleManager.Apply until you are certain it's been applied to all items.  That or you can use Auto and switch to OneTime (or None) after you're sure it's been applied.

ld1453
ld1453

Member

Member

284 points

112 Posts

Re: ISM TraverseDepthFirst Implementation

I understand what you mean but I would suggest that lazy evaluation is not the proper approach to use here because getting the children relies on other processes (ApplyTemplate). In this case, the children themselves don't change, they just haven't been assigned to the Content property of the new ScrollContentPresenter.

Also, what would be the drawback of going ahead and styling the 'old' children (if they indeed change) anyway? If ApplyMode=OneTime, the 'new' children won't get styled anyway and if ApplyMode=Auto we're in the same situation as now.  The cost is traversing and styling children which may never be used but the benefit is not requiring ApplyMode=Auto (or any of the extra effort coding work-arounds) for children that don't actually change.

Don't you agree?

ld1453
ld1453

Member

Member

284 points

112 Posts

Answered Question

Re: ISM TraverseDepthFirst Implementation

 Silverlight 3 seems to work as I expected it to, applying styles to children of even if they might have been changed by the parents style.

  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities