views:

90

answers:

1

FYI I'm pretty new to Silverlight.

Okay, so I want to build a simple user control that contains a button plus some additional XAML as specified by the client of the control.

I got searching on Google and found at least 30 different articles that were all very confusing; especially because they talk about styling animation, customizing other controls that you don't own, and other crap I'm not ready for yet.

This is what I did.

  • In VS 2010, I right clicked and added a new UserControl called MyControl
  • To the MyControl.xaml I changed the LayoutRoot to a StackPanel and added a Button inside it
  • In my MainPage.xaml I added an instance of MyControl
  • I added a TextBox as a child element of this instance
  • I tried to build and got an error that MyControl didn't support Direct Content

Googled some more..

  • I changed MyControl to inherit from ContentControl and updated the xaml
  • I added a ContentPresenter in the xaml to represent the client "custom content"

Okay, it builds and the TextBox shows up, but the Button is missing.

Here's the relevant section from MainPage.xaml

<my:MyControl HorizontalAlignment="Left" Margin="49,26,0,0" x:Name="myContentControl1" VerticalAlignment="Top" Height="550" Width="389">
     <TextBox Height="72" HorizontalAlignment="Left" Margin="166,339,0,0" Name="textBox1" Text="TextBox" VerticalAlignment="Top" Width="460" />
</my:MyControl>

Here's the MyControl.xaml

<ContentControl x:Class="ContentControlTest.MyControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <StackPanel x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}" Orientation="Vertical">
        <ContentPresenter/>
        <Button Content="Button" Height="72" HorizontalAlignment="Left" Margin="78,254,0,0" Name="FooFoo" VerticalAlignment="Bottom" Width="160" />
    </StackPanel>
</ContentControl>

And here is the MyControl.cs

using System.Windows.Controls;

namespace ContentControlTest
{
    public partial class MyControl : ContentControl
    {
        public MyControl()
        {
            InitializeComponent();
        }
    }
}

The way I thought it worked was that the child elements of the control instance are set as the Content property on the ContentControl base class of MyControl. Then, ContentPresenter "pastes" that content into the MyControl.xaml wherever appears.

Although that does seem to be how it works, in the process it is "eating" the Button that I have defined in the MyControl.xaml.

I'm trying not to get into ControlTemplate etc that at this point unless it is absolutely necessary.

Can someone with a clue please tell me what I am doing wrong.

thanks!

+3  A: 

That's because the Content of the control is the entire StackPanel you've written by hand; when you set a new Content, the StackPanel is replaced.

A ControlTemplate is necessary for this scenario, I think; it would be a very simple one after all. The starting point can be the default style of the content control; put the style inside a ResourceDictionary (for instance, in the <ContentControl.Resources> section of your user control), and you're ready to go; all you need to do is add a grid and button inside that template.

Note that the style I linked to sets itself as the default for any reachable ContentControl; to make it only apply to your control and not to any children that may appear inside it, add x:Key="someKey" to the Style and set the ContentControl's Style property explicitly to Style={StaticResource someKey}.

Let me know if you need additional information; also, I might be wrong and there may be an easier way, but I doubt it; the Content property is meant to behave exactly like what you described.

Alex Paven
Thanks Alex, this makes sense. I thought that was what was happening.
octonion
However, your answer has opened up a whole can of worms for me :) I now need to get to grips with ControlTemplate which is currently like voodoo to me. That's good though, because if I can figure that out it opens up a lot of doors. I understand the bit about the Key but you say "put the style inside a ResourceDictionary ... of your user control, and you're ready to go". QUESTION: When you say user control, does it still have to inherit from ContentControl? Thanks again for the help!
octonion
okay, you did mean ContentControl I'm pretty sure. But where do I paste the Grid. I got some errors about VisualTree being set more than once. So I tried various combinations but no luck yet.
octonion
Alex, I got it working! Thank you so much!
octonion