4

I like to create a UserControl with own Header Property.

public partial class SomeClass: UserControl, INotifyPropertyChanged
{
    public SomeClass()
    {
        InitializeComponent();
    }

    private string header;
    public string Header
    {
        get { return header; }
        set 
        { 
            header = value;
            OnPropertyChanged("Header");
        }
    }

    protected void OnPropertyChanged(string propertyName)                    
    {                                                                        
        if (this.PropertyChanged != null)                                    
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

in UserContol xaml:

Label Name="lbHeader" Grid.Column="0" Content="{Binding Path=Header}"

If I set the value: AA2P.Header = "SomeHeeaderText"; than the label.Caption will not changed. How can I solve that problem?

In Windows xaml:

uc:SomeClass x:Name="AA2P" 

If I give directly a value to label (lbHeader.Content = header;) instead of OnPropertyChanged("Header"); its work but, why it does not work with OnPropertyChanged?


I need to use DataContext for somethig else. I try to use dependency property but something is wrong.

public partial class tester : UserControl
{
    public tester()
    {
        InitializeComponent();
    }

    public string Header
    {
        get { return (string)GetValue(MyDependencyProperty); }
        set { SetValue(MyDependencyProperty, value); }
    }
    public static readonly DependencyProperty MyDependencyProperty =
    DependencyProperty.Register("MyDependencyProperty", typeof(string), typeof(string));

}


<UserControl ... x:Name="mainControl">
<TextBlock Text="{Binding ElementName=mainControl, Path=MyDependencyProperty}"/>
</UserControl>


<Window ...>
<my:tester Header="SomeText" />
</Window>

It does not work. What I do wrong? Thanks!

R2D2
  • 43
  • 1
  • 5
  • I don't think it would be a bad idea to post the update as a new question as it changes the scope of the question quite a bit. But maybe I am just grumpy for loosing my accepted answer. Anyhow, I made a try to answer the new question as well, see below. – Avada Kedavra Jul 01 '11 at 21:06

3 Answers3

6

The easiest approach is to just the DataContext of your object. One way of doing that is directly in the constructor like this:

public SomeClass()
    {
        InitializeComponent();
        DataContext = this;
    }

Setting the DataContext will specify where new data should be fetched from. There are some great tips and information in the article called WPF Basic Data Binding FAQ. Read it to better understand what the DataContex can be used for. It is an essential component in WPF/C#.


Update due to update of the question.

To my understanding you should change the first argument of DependencyProperty.Register to the name of the property that you want to bind to, here "Header" as well as the second argument to the type of your class, here SomeClass. That would leave you with:

public static readonly DependencyProperty MyDependencyProperty =
    DependencyProperty.Register("Header", typeof(SomeClass), typeof(string));

But i seldom use dependency properties so I am not positive that this is it, but its worth a try..

Avada Kedavra
  • 8,523
  • 5
  • 32
  • 48
  • Thanks! I should ask it 3 hours ago :-) – R2D2 Jul 01 '11 at 13:11
  • Thanks! I was already tired and I have overlooked it. Sorry for the Update. I should seek more: [link](http://stackoverflow.com/questions/771833/how-to-bind-to-a-wpf-dependency-property-when-the-datacontext-of-the-page-is-used) – R2D2 Jul 03 '11 at 10:19
2

If you need the Data context for something else. You can also utilize the ElementName property in the Binding.

    <UserControl
        x:Class="MyControl.MyUserControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="mainControl">
        <TextBlock Text="Binding ElementName=mainControl, Path=MyDependencyProperty}"/>
    </UserControl>

[Edit]

I should add something. Make the "Header" property a dependency property, this will make your live much easier. In UI Controls you should make property almost always a dependency property, every designer or user of your control will thank you.

dowhilefor
  • 10,971
  • 3
  • 28
  • 45
  • Thanks for the suggestion, I going to use dependency property. – R2D2 Jul 01 '11 at 13:19
  • As you described, I need to use DataContext yet what about different. I have completed my post. Could you please look at it? Thanks! – R2D2 Jul 01 '11 at 20:39
1

The UserControl itself needs the DataContext of where it is used later. But the controls inside the UserControl need the UserControl as their DataContext, otherwise they also will inherit the DataContext from the later usage context. The trick is to set the DataContext of the UserControl's child to that of the UserControl, so it now can use the dependency properties of the UserControl.

<UserControl x:Class="MyControl.MyUserControl">
  <Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor,
      AncestorType=UserControl,AncestorLevel=1}}">...</Grid>
</UserControl>

If you do this this way the children of the Grid can have simple {Binding dp's name} without additionally ElementName parameters.

dedlfix
  • 41
  • 3
  • I prefer this method to naming the user control and using ElementName binding. However you will find binding to the template parent easier in custom control classes instead of user controls, though you lose the design time WYSIWYG editor. – Chris Schaller Mar 20 '17 at 09:47