简体   繁体   中英

How to expose view-model properties as externally bindable dependency properties?

I'm writing a WPF user control which internally uses MVVM. In order to work out-of-the-box, it creates its own view-model (this part is not relevant to the question).

My control exposes a number of dependency properties. The host view (whoever uses my control) can set these DPs or bind to them. Some of these DPs have corresponding view-model properties.

This is what I want to achieve (see diagram): the DPs in my control's view are bound to the corresponding properties of the view-model. Additionally, the host view needs to be able to set or bind these DPs, too - the same way you use any other control.

However, as soon as the host view sets or binds the DP's value, the original binding (binding it internally to the control's view-model) is lost. This is because every DP can only have a single binding set. So this doesn't work:

什么不起作用的图

One solution is to make the view-model a DependencyObject and its properties DPs. This way, I could bind the control's view-model to its view rather than the other way around, effectively reversing the left arrow. However, for various reasons, I want my view-model to use plain C# properties and INotifyPropertyChanged.

Any ideas on how to expose view-model properties as externally bindable dependency properties?

Edit:

To clarify on the requirements: the view does not in fact create the view-model itself (I realize that would violate the separation of concerns); rather, it uses a view-model locator to do so. (It's a terribly modular enterprise application.) I know this is not a typical approach (see Rachel's answer). However, accepting the described set-up, is there any way to achieve the desired result?

If I'm creating a ViewModel for a CustomControl , it is expected that the user will use that ViewModel as the CustomControl.DataContext . Any other time, my UserControl's don't have ViewModels associated with them.

For example, suppose I wanted a PopupControl.

I would either create a UserControl with all custom properties and logic in the code-behind the UserControl (no ViewModel)

<local:Popup Header="{Binding PopupHeader}"
             IsVisible="{Binding IsVisible}" />

OR

I would create a PopupViewModel and build my PopupUserControl expecting that the DataContext will be of type PopupViewModel

<DataTemplate DataType="{x:Type local:PopupViewModel}">
    <local:PopupView />
</DataTemplate>

<ContentControl Content="{Binding MyPopupViewModel}" />

Properties like IsVisible or PopupHeader would exist in the ViewModel , not in the PopupUserControl

So the situation is that you have VM and View, they must be data bound to each other and VM can`t be DependencyObject ? Well, triple binding VM-V-Host is not possible, AFAIK.

One possible approach is to make duplicate set of DependencyProperties in View. Original properties will be bound to VM and will affect the look of View, duplicate properties will be bound to Host and somehow affect the VM (with DP changing logic, for example).

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