views:

300

answers:

1

I would like to update the default Window style dynamically at runtime so I can change the FontSize and FontFamily dynamically at runtime. I found that Styles in your resource dictionary are sealed at runtime and cannot be changed, so I used the following method of updating the style:

<Style TargetType="{x:Type Window}">
    <Setter Property="FontFamily" Value="Arial"/>
    <Setter Property="FontSize" Value="12pt"/>
</Style>

Style newStyle = (Make a copy of the old style but with the FontSize and FontFamily changed)

// Remove and re-add the style to the ResourceDictionary.
this.Resources.Remove(typeof(Window));
this.Resources.Add(typeof(Window), newStyle);

// The style does not update unless you set it on each window.
foreach (Window window in Application.Current.Windows)
{
    window.Style = newStyle;
}

There are several problems with this approach and I have a few questions as to why things are the way they are.

  1. Why are styles sealed at runtime and is there a way of making them unsealed?
  2. When I re-add the new style, why is this not picked up by all of my windows? Why do I have to go and manually apply it to every window?
  3. Is there a better way?
+1  A: 

I would probably tackle this with a "settings service" which exposes properties for the various settings, and fires INPC as you would for normal binding. Next up I'd change that style to be something like:

<Style x:Key="MyWindowStyle">
    <Setter Property="FontFamily" Value="{Binding Path=FontFamily, Source={StaticResource SettingsService}, FallbackValue=Arial}"/>
    <Setter Property="FontSize" Value="{Binding Path=FontSize, Source={StaticResource SettingsService}, FallbackValue=12}"/>
</Style>

With your "settings service" defined as a static resource:

<services:SettingsService x:Key="SettingsService"/>

Then in each window make sure the style is set as a DynamicResource:

<Window Style="{DynamicResource MyWindowStyle}" .... >

There is often a lot of misunderstanding around the differences between Static and Dynamic resources, but the basic difference is Static is a "one time" setting whereas Dynamic will update the settings if the resource changes.

Now if you set those properties in your "settings service" they will fire INPC, which will update the Style, which the DynamicResource will pick up on and alter the Window properties accordingly.

Seems like a lot of work, but it gives you some nice flexibility, and all the "heavy lifting" is done purely using Bindings. We use a similar technique on a project I'm working on at the moment so when a user chooses a fill/stroke colour the various tools in the toolbar update to reflect the new values.

Steven Robbins