1

I am trying to instantiate a control in my window's code behind (for Frame Navigation). Unfortunately, it's not getting the default style applied to it.

I would expect that when a control is first rendered, the renderer would set the control's Style/Template to either (the explicitly supplied one -> the default one supplied in the resources -> null).

Is my mental model of how default styles are applied wrong? Is it actually like how

class Whatever
{
    int value = 5;
}

is really syntactic sugar for

class Whatever
{
    public Whatever()
    {
        this.value = 5;
    }

    int value;
}

And thus the Style is being set at compile time?

Could it be a problem stemming from how I'm accessing the Styles and Templates for the control (unlikely as I can make a control of it's type on my main window and it has the default Style)?

MainWindow.xaml

<Window>
    <Window.Resources>
        <ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="DataLogPage/Themes.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <!-- Data here... -->
</Window>

DatalogPage/Themes.xaml

<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Themes/Styles/DefaultStyle.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

DatalogPage/Themes/Styles/DefaultStyle.xaml

<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="../Templates/DefaultTemplate.xaml" />
    </ResourceDictionary.MergedDictionaries>
    <Style TargetType="this:DataLog">
        <Setter Property="Template"
                Value="{StaticResource DefaultTemplateForDataLog}" />
    </Style>
</ResourceDictionary>

DatalogPage/Themes/Templates/DefaultTemplate.xaml

<ResourceDictionary>
    <ControlTemplate x:Key="DefaultTemplateForDataLog"
                     TargetType="this:DataLog">
        <!-- Data here... -->
    </ControlTemplate>
</ResourceDictionary>

MainWindow.xaml.cs (where I'm creating the control in the code behind)

private void currentContext_ContextChangeRequested()
{
    //Other bits of logic for context switching

    //User wants to go to the Data Log Page
    this.MainFrame.Navigate(new DataLogPage.DataLog());
    return;
}

To reiterate:

Problem: Control created in code behind does not have it's default Style.

Possible ideas on why this may be:

1)My user model for how default styles are applied is wrong and I must set it explicitly.
2)I may be referencing the style incorrectly.

If I have to explicitly set the Style/Template, is there a best-of-both-worlds where I can make something in the MainWindow's xaml that I can programmatically reference like so: new DataLogPage.DataLog(){Style = this.DataLogStyle};?

Tory
  • 520
  • 3
  • 13

1 Answers1

1

App.xaml

If you really want stuff shared you may inject them into the shared application resources, or you may merge them in app.xaml

<Application x:Class="BlaBla"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="MainWindow.xaml">
   <Application.Resources>
     <ResourceDictionary>
       <ResourceDictionary.MergedDictionaries>
          <ResourceDictionary Source="A.xaml"/>
          <ResourceDictionary Source="B.xaml"/>
       </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
  </Application.Resources>
</Application>

Using a global ResourceDictionary in a UserControl Library

WPF - Global Style?

Templates and cust controls

Applies to customcontrols only (**)

First off I would never start merging or using dictionaries that way in a window(That's if you go the cc way, your rather merge these dictionaries in the generic files described below, note they must be in scope though). You have a folder called Generic, which must have a file called Themes.xaml present. Personally I merge alot of dictionaries here and also do some "manual labor". Typically i call my cust control Foo's theme ThemeName.generic.xaml, but that's just my preference. :).

A customcontrol should derrive from control and it must have the following static constructor, for having it's template applied.

public class Whatever : Control // from scratch or something you want to extend
   static Whatever()
   {
       DefaultStyleKeyProperty.OverrideMetadata(typeof (Whatever), new FrameworkPropertyMetadata(typeof (Whatever)));
   }
}

<Style TargetType="{x:Type local:Whatever}">
    <!-- Do whatever here ;) -->
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:Whatever}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Override OnApplyTemplate to see if the template is applied. (*)

Styles

Applies to styling.

To override an existing controls template you do the following in themes.xaml. This will make all your button controls have this style by default.

 <Style TargetType="{x:Type Button}">
    <Setter Property="Background" Value="Green"/> 
 </Style>

I often just put styles directly in ie a usercontrol's resources, but mostly data,itemptemplates etc if they don't belong in a cust control, anyways this is how to do that:

<UserControl.Resources>
    <!-- usuallly  just datatemplates, itemtemplates etc.. -->
    <Style x:Key="SomeStyle" TargetType="{x:Type Button}">
        <!--whatever -->
        <Setter Property="Background" Value="Black"/>
    </Style>
</UserControl.Resources>
<Button Style="{StaticResource SomeStyle}"></Button>

BTW: You may load most things dynamicly and even from other assemblies. Resources, templates the works. But that's another subject :)

Hope it helped you some,

Cheers

Stian

Community
  • 1
  • 1
Stígandr
  • 2,874
  • 21
  • 36
  • 1
    Moving the merge dictionaries to a ResourceDictionary pointed to by the `App.xaml` worked. Is there anything I would have to look out for in doing it this way? Also, I can't see a difference using `DefaultStyleKeyProperty.OverrideMetadata` (the style is applied either way). – Tory Aug 18 '14 at 21:18
  • @Tory yeah that works indeed. I didn't fully finnish my post here, because my phone rang, but I found that link for you there :) The override I only use when I create what's called custom controls. If you just want to apply styles you may do that, and you also use behaviours (I love them) and Attached Properties to extend functionality of controls. – Stígandr Aug 18 '14 at 21:56
  • @Tory I updated the answer there adding and example of app.xaml and merging dictionaries there. – Stígandr Aug 18 '14 at 22:02
  • Yeah, I am (in this case) applying this to a custom control. And I already knew about using ` – Tory Aug 18 '14 at 22:14