DependencyProperty does not work if the value is from a binding

↘锁芯ラ 提交于 2021-02-05 12:34:14

问题


I created UserControl with viewmodel. It has DependencyProperty which only works if the value is passed directly. If the value is passed through the binding, it no longer works.

Here is the view code:

This is a closed element not associated with any other. All listed items belong to him. This is a code shortening, I am not going to present whole, immeasurable structures.

View

public partial class SomeView : UserControl
{
    public SomeView()
    {
        InitializeComponent();
        SetBinding(ActiveProperty, new Binding(nameof(SomeViewModel.Active)) { Mode = BindingMode.OneWayToSource });
    }

    #region ActiveProperty
    public static readonly DependencyProperty ActiveProperty = DependencyProperty.Register(nameof(Active), typeof(bool), typeof(VNCBoxView));

    public bool Active
    {
        get { return (bool)GetValue(ActiveProperty); }
        set { SetValue(ActiveProperty, value); }
    }
}

VievModel

public class SomeViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool active;

    public bool Active
    {
        get { return active; }
        set
        {
            active = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Active)));
        }
    }
}

UserControl

<UserControl ...>
    <UserControl.DataContext>
        <viewModels:SomeViewModel />
    </UserControl.DataContext>
    <Grid>
        <TextBlock Text="{Binding Active}" />
    </Grid>
</UserControl>

===================================================

When working with a ready component, which is an individual, separate entity, the problem occurs depending on how it is used. I remind you that the elements used in the view in question are a closed whole that does not connect with the element in which it is used. It is the transfer of value that is the matter of the problem.

This is working usage:

<local:SomeView Active="True" />

In viewmodel, the setter is invoked twice, once with false and then with true.

If the value comes from binding, it doesn't work:

<local:SomeView Active="{Binding SomeParentProperty}" />

In viewmodel, setter is only called once with the value false.

Setters in a view are never called, in both cases.

Please help


回答1:


There is no IsConnected property in the SomeViewModel instance in the current DataContext of the UserControl, hence the Binding

<local:SomeView Active="{Binding IsConnected}" />

won't work. It tries to resolve the PropertyPath against the current DataContext, unless you explicitly specify its Source, RelativeSource or ElementName.

This is the exact reason why UserControls should never explicitly set their own DataContext, and hence never have something like an own, private view model.

The elements in the UserControl's XAML would not bind to properties of such a private view model object, but directly to the properties of the UserControl, for example like

<TextBlock Text="{Binding Active,
    RelativeSource={RelativeSource AncestorType=UserControl}}"/>



回答2:


When you set the DataContext explicitly in the UserControl like this:

<UserControl.DataContext>
    <viewModels:SomeViewModel />
</UserControl.DataContext>

...you can no longer bind to SomeView's DataContext in the consuming view like this:

<local:SomeView Active="{Binding IsConnected}" />

...because SomeViewModel doesn't have any IsConnected property.

You should avoid setting the DataContext explicitly and let the UserControl inherit its DataContext from its parent element. You can still bind to the dependency property of the UserControl itself using a RelativeSource or an ElementName:

<UserControl ...>
    <Grid>
        <TextBlock Text="{Binding Active, RelativeSource={RelativeSource AncestorType=UserControl}}" />
    </Grid>
</UserControl>

Besides, SomeViewModel seems superfluous in your example since the UserControl already has an Active property.



来源:https://stackoverflow.com/questions/58118486/dependencyproperty-does-not-work-if-the-value-is-from-a-binding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!