views:

104

answers:

1

Hello,

I have a custom base user control in silverlight.

<UserControl x:Class="Problemo.MyBaseControl"
    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"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <Border Name="HeaderControl" Background="Red" />
    </Grid>
</UserControl>

With the following code behind

public partial class MyBaseControl : UserControl
    {
        public UIElement Header { get; set; }

        public MyBaseControl()
        {
            InitializeComponent();
            Loaded += MyBaseControl_Loaded;
        }

        void MyBaseControl_Loaded(object sender, RoutedEventArgs e)
        {
            HeaderControl.Child = Header;
        }
    }

I have a derived control.

<me:MyBaseControl x:Class="Problemo.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"
    xmlns:me="clr-namespace:Problemo" 
    d:DesignHeight="300" d:DesignWidth="400">
    <me:MyBaseControl.Header>
        <TextBlock Name="header" Text="{Binding Text}" />
    </me:MyBaseControl.Header> 
</me:MyBaseControl>

With the following code behind.

 public partial class MyControl : MyBaseControl
    {
        public string Text
        {
            get; set;
        }

        public MyControl(string text)
        {
            InitializeComponent();
            Text = text;
        }
    }

I'm trying to set the text value of the header textblock in the derived control.

It would be nice to be able to set both ways, i.e. with databinding or in the derived control code behind, but neither work. With the data binding, it doesn't work. If I try in the code behind I get a null reference to 'header'. This is silverlight 4 (not sure if that makes a difference)

Any suggestions on how to do with with both databinding and in code ?

Cheers

A: 

First of all I'll show you how to adjust your Derived control to handle this. You need to do two things, first you need to implement INotifyPropertyChanged and secondly you to add the binding to the user control.

MyControl Xaml:-

<me:MyBaseControl.Header>     
    <TextBlock Name="headerItem" />     
</me:MyBaseControl.Header>

MyControl code:-

public partial class MyControl : MyBaseControl, INotifyPropertyChanged
{
    public MyControl ()
    {
        InitializeComponent();
        headerItem.SetBinding(TextBlock.TextProperty, new Binding("Text") { Source = this });
    }

    string _text;
    public string Text
    {
        get { return _text; }
        set { _text = value; NotifyPropertyChanged("Text"); }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

    #endregion
}

This should get you working. However, as soon as you feel you need to inherit a UserControl based class you should take a step back and ask whether the base and derived items ought to be templated controls instead. If I get time I'll try to add a version of your code in terms of templated controls.

AnthonyWJones
Thanks.The base class is templated(its pretty much a window,which has a title,content,minimize/maximise)If I change the base control in this example to be a templated control,the code fails with headerItem being null.Any suggestions on getting it 2 work with templated base control?public class MyBaseControl:Control{public UIElement Header{get;set;}public MyBaseControl(){DefaultStyleKey=typeof(MyBaseControl);}public override void OnApplyTemplate(){base.OnApplyTemplate();var headerControl = GetTemplateChild("HeaderControl") as Border;if(headerControl!=null)headerControl.Child = Header; }}
Mrt
@Mrt: I'm not suggesting that you should be using a templated control just that it might have been worth considering. Now that you have revealed more about what you are doing, is there any reason you are not using the built-in `ChildWindow` class? BTW, code doesn't format in a comment, if you want to persue the templated control approach post another question.
AnthonyWJones
New question posted. http://stackoverflow.com/questions/2627410/how-to-access-a-named-element-in-a-control-that-inherits-from-a-templated-control
Mrt