简体   繁体   中英

Binding dependency property - set in custom user control, get in viewmodel

The aim is to instantiate an object in a custom UserControl and then access that instance from a viewmodel. But the following is not working, the UpRatings property in the viewmodel is null.

Custom UserControl with Dependency Property

public partial class Scale:UserControl
{

    public Scale()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty MouseRatingsProperty = 
        DependencyProperty.Register(
        "MouseRatings",
        typeof(IObservable<double>),
        typeof(Scale));

    public IObservable<double> MouseRatings
    {
        get
        {
            return (IObservable<double>)GetValue(MouseRatingsProperty);
        }
        set
        {
            SetValue(MouseRatingsProperty, value);                
        }
    }

    // requires System.Reactive NuGet
    private ISubject<double> _mouseRatings = new Subject<double>();

    protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);
        // _mouseRatings is the object instance I need to access in the viewmodel
        MouseRatings = _mouseRatings;
    }
}

View

<StackPanel>
    <scale:Scale MouseRatings="{Binding Path=UpRatings, Mode=TwoWay}"/>
</StackPanel>

ViewModel

// requires Prism.Wpf NuGet
public class MyViewModel : BindableBase
{
    public IObservable<double> UpRatings { get; set; }

    // called after the DataContext is set, so the UpRatings binding should work here by now
    // see https://github.com/PrismLibrary/Prism/blob/master/Documentation/WPF/60-Navigation.md
    public void OnNavigatedTo(NavigationContext navigationContext)
    {
        // but UpRatings is unfortunately null here
        Trace.WriteLine(UpRatings == null ? "null" : "not null");
    }

}

Note that the DataContext is not set directly on the custom usercontrol but a parent of hers (and I can confirm that inside the custom usercontrol).

It started to work when MouseRatings = _mouseRatings; is called later as follows, while MouseRatings lost its value for some mysterious reason if setting it OnInitialized.

public Scale()
    {
        InitializeComponent();
        IsVisibleChanged += Scale_IsVisibleChanged;
    }

private void Scale_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if (IsVisible)
        {
            MouseRatings = _mouseRatings;
        }
    }

It would also work to set it in the UserControl Loaded event, but then the viewmodel has to wait extra time before being able to access the object.

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