简体   繁体   中英

Custom dependency property isn't getting binded input

I'm creating a UserControl with a DependencyProperty but the DependencyProperty isn't getting the value that the caller is passing in.

I've discovered the following during my own investigation

  • If I use a built-in user control, such as TextBlock, everything works. This narrows the problem down to my UserControl's implementation (as opposed to the code that calls the UserControl)

  • My property changed callback that I register isn't even being called (well... at least the breakpoint isn't being hit)

  • If only see this problem when I use a binding to provide the dependency property, so this doesn't work :

     <common:MyUserControl MyDP="{Binding MyValue}"/> 

    but I have no problems if I get rid of the binding and hardcode the value, so this works :

     <common:MyUserControl MyDP="hardCodedValue"/> 

Here's my UserControl's code behind:

public partial class MyUserControl : UserControl
{
    public string MyDP
    {
        get { return (string)GetValue(MyDPProperty); }
        set { SetValue(MyDPProperty, value); }
    }

    public static readonly DependencyProperty MyDPProperty =
        DependencyProperty.Register(
            "MyDP", 
            typeof(string), 
            typeof(MyUserControl),
            new FrameworkPropertyMetadata(
                "this is the default value",
                new PropertyChangedCallback(MyUserControl.MyDPPropertyChanged)));

    public static void MyDPPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        ((MyUserControl)obj).MyDP = (string)e.NewValue;
    }

    public MyUserControl()
    {
        InitializeComponent();
        this.DataContext = this;
    }
}

And here's the xaml

<Grid>
    <TextBlock Text="{Binding MyDP}"/>
</Grid>

Since I'm able to use built-in user controls such as TextBlock, I don't think that the error lies in my host code, but here it is, just so that you have a complete picture:

<StackPanel>
    <common:MyUserControl MyDP="{Binding MyValue}"/>
</StackPanel>

public class MainWindowViewModel
{
    public string MyValue { get { return "this is the real value."; } }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainWindowViewModel();
    }
}

This line in the UserControl is wrong:

this.DataContext = this;

This makes the UserControl its own DataContext, so the binding is looking for a property called MyValue on the UserControl, and that property does not exist. You want the DataContext to be your view-model. If you don't set it explicitly, it will inherit the DataContext from its container (the Window in this case).

Delete that line, and you'll be closer. You also don't need that callback; remove that too.

You can update your control's view code like that:

 <Grid>
        <TextBlock x:Name="_textBlock"/>
    </Grid>

And set a _textBlock's text property in MyDPPropertyChanged method:

public static void MyDPPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var control = ((MyUserControl)obj);
        control.MyDP = (string)e.NewValue;
        control._textBlock.Text = control.MyDP;
    }

That will do the trick.

Kindly Implement INotifyPropertyChanged, and PropertyChangedEventHandler in side the control and also the viewmodel. secondly use SetCurrentValue method to set the value inside the control class rather setting it directly

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