简体   繁体   中英

WPF: Is it possible to bind to a parent on userControl property and set its DataContext to a viewmodel?

I got stuck on this for a while before i even found out why things was not working. I'm changing the visibility on two different UserControls based on the value of Connected which is a property on the SetupViewModel(parent). One of these usercontrols also have its DataContext set to a viewmodel that is created in the SetupViewModel. But the binding to connect does not work when also setting the DataContext.


This is how i would like it to work

<userControls:SessionSetupUserControl x:Name="SessionSetupUserControl" DataContext="{Binding SessionSetupViewModel}" Visibility="{Binding Connected, Mode=OneWay, Converter={StaticResource BoolToVis}, FallbackValue=Collapsed}" />

But when using this the Visibility value will not update.


When i remove the DataContext the visibility starts to update.

<userControls:SessionSetupUserControl x:Name="SessionSetupUserControl" Visibility="{Binding Connected, Mode=OneWay, Converter={StaticResource BoolToVis}, FallbackValue=Collapsed}" />

This is the parent ViewModel. Only showing the relevant bindings.

public class SetupViewModel : BindableBase
{
    private bool _connected;

    public SessionSetupViewModel SessionSetupViewModel { get; private set; }

    public bool Connected
    {
        get
        {
            return _connected;
        }
        private set
        {
            SetPropertyAndNotifyChanges(ref _connected, value);
        }
    }
}

I assume that the DataContext of the UserControl is changed when the visibility binding is resolved but i'm not that used to working with WPF nor bindings so i've not been able to get it working.

Any help would be most appreciated.

You can always bind to a property in the DataContext of a control's Parent element like this:

Visibility="{Binding Parent.DataContext.Connected,
                     RelativeSource={RelativeSource Self},
                     Converter={StaticResource BoolToVis}}"

You may however consider a different design, where your UserControl does not directly bind to an explicitly assigned DataContext.

The control could expose dependency properties that are bound when you instantiate it. It would thus become independent of any particular view model.

<userControls:SessionSetupUserControl
    Visibility="{Binding Connected, Converter={StaticResource BoolToVis}}"
    SomeProperty="{Binding SessionSetupViewModel.SomeVmProperty}"
    SomeOtherProperty="{Binding SessionSetupViewModel.SomeOtherVmProperty}"
    .../>

Another option for bindings would be to nest the control...

<UserControl Visibility="{Binding Connected, Mode=OneWay, Converter={StaticResource BoolToVis}, FallbackValue=Collapsed}" >

    <userControls:SessionSetupUserControl x:Name="SessionSetupUserControl" 
        DataContext="{Binding SessionSetupViewModel}" />

</UserControl>

This way, the outer generic "UserControl" has its bindings directly to itself and can be visible/hidden/collapsed based on your converter.

Then the inner user control is specifically bound to the data context of the SessionSetupViewModel

Since you changed the DataContext for your SessionSetupUserControl instance, other bindings are trying to resolve on the DataContext you assigned.

This means that your binding for Visibility is looking for a property named "Connected" on SessionSetupViewModel.

Pay attention to the Visual Studio output log when debugging, you must be seeing binding errors that say pretty much this.

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