简体   繁体   中英

How to use bound XAML property in UserControl?

I have my own UserControl

 <local:MyUserControl MyProperty="{Binding myString}"/>                                      

and I'm binding myString to it. Now I want to use it in my UserControl . I have DependencyProperty defined in my UserControl :

    public string MyProperty
    {
        get { return (string)GetValue(MyPropertyProperty); }
        set
        {
            Debug.WriteLine(value);//writes nothing, null
            SetValue(MyPropertyProperty, value);
        }
    }
    public static readonly DependencyProperty MyPropertyProperty =
      DependencyProperty.Register("MyProperty", typeof(string), typeof(MyUserControl), new PropertyMetadata(null));

What am I doing wrong? I want to do some things with this string. But it's always null.

The Debug.WriteLine(value); writes nothing not because the value is null . The getter and setter of a dependency property are not guaranteed to be run, while using {Binding} , the setter of your property is not called. You can add a break point in the setter to test it.

Please note following caution in Custom dependency properties :

In all but exceptional circumstances, your wrapper implementations should perform only the GetValue and SetValue operations. Otherwise, you'll get different behavior when your property is set via XAML versus when it is set via code. For efficiency, the XAML parser bypasses wrappers when setting dependency properties; whenever possible, it uses the registry of dependency properties.

Instead of reacting in the setter of your property, you can add a property changed handler in the original call to DependencyProperty.Register and in this handler you can act on the new value. For example:

public string MyProperty
{
    get { return (string)GetValue(MyPropertyProperty); }
    set
    {
        SetValue(MyPropertyProperty, value);
    }
}

public static readonly DependencyProperty MyPropertyProperty =
  DependencyProperty.Register("MyProperty", typeof(string), typeof(MyUserControl), new PropertyMetadata(null, OnPropertyChanged));

private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if ((string)e.NewValue != (string)e.OldValue)
    {
        Debug.WriteLine(e.NewValue);
    }
}

If you want to use the bound string in your UserControl , you can use MyProperty of the UserControl . For example:

In your UserControl :

<UserControl Name="root" ...>
    <StackPanel>
        <TextBlock Text="{Binding MyProperty, ElementName=root}" />
    </StackPanel>
</UserControl> 

Then when you use <local:MyUserControl MyProperty="{Binding myString}"/> , your UserControl will show the value of myString .

If you used c# naming conventions - fields are camelcase - you bound this stuff to a field ( myString ). It's not working. You have to bind to a property (Pascalcase - get;set; ...etc). In this case, you have a binding error in your output window.

Default setup of dependency property is OneWay binding which means if usercontrol changes the string it does not reflect in DataContext.

Change your binding to TwoWay

<local:MyUserControl MyProperty="{Binding myString, Mode=TwoWay}"/>      

or change your DependencyProp to TwoWay mode:

DependencyProperty.Register("MyString", typeof(string), typeof(MyUserControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM