views:

42

answers:

1

As a follow up to this question where it was suggested I use a ContentControl, I have run into a scenario when I use a custom made class that dervies from ContentControl on a page, any controls defined within that ContentControl are not accessible from the page. All member variables turn out null.

For Instance, say the custom class I created that derives from ContentControl is named MyGroupBox and I try to use this inside a Page control:

<UserControl x:Class="MyApplication.MyUserControl">
   <local:MyGroupBox Title="Basic Information">
      <TextBox x:Name="MyTextBox" />
   </local:MyGroupBox>
</UserControl>

When I try to access MyTextBox from within the Page's code behind, the member variable is null. What is the best workaround for this scenario to get access to these controls so that I can use them in the Page's code behind?

Thanks!

EDIT: Here is the Default Template for the MyGroupBox control

<Style TargetType="local:MyGroupBox">
    <Setter Property="Foreground" Value="#FF000000"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MyGroupBox">
                <Border BorderThickness="1" Margin="8,8,0,0">
                    <Border.BorderBrush>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                            <GradientStop Color="#FF979797" Offset="0"/>
                            <GradientStop Color="#FFF1F1F1" Offset="1"/>
                        </LinearGradientBrush>
                    </Border.BorderBrush>
                    <StackPanel>
                        <Grid>
                            <Rectangle>
                                <Rectangle.Fill>
                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                        <GradientStop Color="White" Offset="0"/>
                                        <GradientStop Color="#FFDFE2ED" Offset="1"/>
                                    </LinearGradientBrush>
                                </Rectangle.Fill>
                            </Rectangle>
                            <TextBlock Text="{TemplateBinding Title}" Margin="10,3,3,3" TextAlignment="Center" HorizontalAlignment="Left" />
                        </Grid>
                        <ContentPresenter Cursor="{TemplateBinding Cursor}" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </StackPanel>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>    

EDIT:

public MyUserControl()
{
    InitializeComponent();

    if (this.MyTextBox == null)
    {
        // MyTextBox is null at this point - is there a way to get 
        // the InitializeComponent method to find the control named MyTextBox when
        // it is inside of a ContentControl derived class?
        MessageBox.Show("MyTextBox is null");
    }
}
+1  A: 

Let me step you through putting it together by showing the steps I took to test what you posted:-

  • In Visual Studio create a Silverlight Application

  • Add a new item to the Silverlight project selecting "Silverlight Templated Control", call this "MyGroupBox".

  • Open the Themes\Generic.xaml which will now have been created. It will contain the a style:-

Generic.Xaml:-

<Style TargetType="local:MyGroupBox">
   ...
</Style>
  • Replace its entire content with the content in your question.

  • Edit MyGroupBox.cs, modify to inherit from ContentControl and add Title dependency property.

MyGroupBox.cs:-

public class MyGroupBox : ContentControl
{
    public MyGroupBox()
    {
        this.DefaultStyleKey = typeof(MyGroupBox);
    }

    #region public string Title

    public string Title
    {
        get { return GetValue(TitleProperty) as string; }
        set { SetValue(TitleProperty, value); }
    }

    public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register(
                    "Title",
                    typeof(string),
                    typeof(MyGroupBox),
                    new PropertyMetadata(null));
    #endregion public string Title

}
  • Open MainPage.Xaml add some usage for MyGroupBox

In MainPage.xaml

<Grid x:Name="LayoutRoot">
    <StackPanel>
        <local:MyGroupBox Title="Test" HorizontalContentAlignment="Stretch">
            <TextBox x:Name="MyTextBox" />
        </local:MyGroupBox>
    </StackPanel>
</Grid>
  • Edit the MainPage.xaml.cs to test whether MyTextBox is null

    public MainPage()
    {
        InitializeComponent();
        MessageBox.Show((MyTextBox == null).ToString());
    }
    

I get "False", InitializeComponent has succesfully found the element with the name "MyTextBox".

AnthonyWJones
Thanks for your effort. The problem was that when I created the MyGroupBox class, I had done so by adding a UserControl to the project (which includes a XAML file - i.e. - MyGroupBox.xaml and MyGroupBox.xaml.cs). What I should have done instead is just added a normal .cs file MyGroupBox.cs and derived from ContentControl in that just as you show in your answer.
Andrew Garrison