views:

931

answers:

1

I'm new to Silverlight and I wanted to accomplish a relatively simple task:
   Create a "panel" control that would display a heading and some child content.

I was able to get this work to a degree, but the placement of the XAML really confuses me.

On my page I use my control. This results in my panel being shown with a button in the child content area which is blue, with a 20px yellow heading at the top saying "Below is some content".

<UserControl x:Class="SilverlightApplication9.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:SilverlightApplication9">
    <Grid Background="White">        
        <local:MyPanel Background="Blue">            
                <Button Width="50" Height="25" Content="Hello"></Button>            
        </local:MyPanel>    
    </Grid>
</UserControl>

My panel source code is simple, just:

public partial class MyPanel : ContentControl
{
    public MyPanel()
    {
        DefaultStyleKey = typeof(MyPanel);   
        InitializeComponent();         
    }
}

It's a partial class, and there is an attached XAML file, which is where my confusion starts:

If I try placing my style/template code into the partial class XAML file, it seems to be ignored (my button is shown, but the other content like the colors and text is missing)

<ContentControl x:Class="SilverlightApplication9.MyPanel"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:SilverlightApplication9">
    <ContentControl.Resources>
        <ResourceDictionary>
            <Style TargetType="local:MyPanel">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="local:MyPanel">
                            <Grid Background="Yellow">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="20" />
                                    <RowDefinition />
                                </Grid.RowDefinitions>
                                <TextBlock HorizontalAlignment="Center" Height="20" Grid.Row="0" Text="Below is some content"/>
                                <Grid Grid.Row="1" Background="LightBlue">
                                    <ContentPresenter />
                                </Grid>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ResourceDictionary>
    </ContentControl.Resources>
</ContentControl>

However if I create a \Themes\generic.xaml file and paste in the same code, it works

<ResourceDictionary 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:SilverlightApplication9"
  xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
  >
    <Style TargetType="local:MyPanel">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:MyPanel">
                    <Grid Background="Yellow">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="20" />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <TextBlock HorizontalAlignment="Center" Height="20" Grid.Row="0" Text="Below is some content"/>
                        <Grid Grid.Row="1" Background="LightBlue">
                            <ContentPresenter />
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

I'm clearly missing something important about how resources or XAML files are processed or used in a project (I did not have any experience with WPF before Silverlight).

What am I doing wrong that is preventing me from just putting the panel's template code into the panel's xaml file? Are there some concepts regarding XAML and resources that I'm getting wrong?

+2  A: 

David, you need to create a key for your style, and reference it in the panel via it's Style property ... it is a limitation of Silverlight, that it does not let you create "global" styles that apply to all elements of some type.

This behaviour is different when you place the style in themes, as you noticed.

Another alternative is to place the style in the ResourceDictionary of the panel itself and not the page/user control, but then you cannot reuse that style in other panels.

Ireney Berezniak
I've noticed that when done by theme, it will override the parent themes (a button inside my panel gets the generic look even if I've added something like TwilightBlue to the page). Could you expand on the third option, placing the style in the ResourceDictionary of "the panel itself" - I'm not entirely sure how that works. Do you mean placing the style into every instance of the panel (so the style would go just before the button and other child content)? I also want to eventually add some behavoir - should I perhaps pursue a programic approach, by overriding the AddChild method?
David
To elaborate, with the programmatic approach I'd abandon using Styles and xaml, and instead populate the control by manually creating the sub-components (like my header) in the cs file, and then override the mechanism to set content so that it is instead placed in the correct sub-component. I haven't actually tried any of the above yet, it just seems like another way of doing what I want (I want to create a small number of panel, i.e. a panel with a standard header, a dialog/window style panel, etc)
David
Yes, each element can have it's own resource dictionary, so the style would be placed into every instance of the panel. I don't recommend using the programmatic approach, as I prefer a clear separation between the view and the presenter or presentation model ... I'm a follower of the Model-View-ViewModel pattern. It seems that you should be able to accomplish your task by XAML alone, and data binding. Instead of creating your own panel, have you considered using one of the existing elements, like grid, or stackpanel, and ovewrite the template to create what you need?
Ireney Berezniak