简体   繁体   中英

Expose child properties of user control directly as property of user control

Without breaking MVVM, is there a way to expose some properties of a child control in a user control so that the window or other user control that utilizes it can access these properties directly?

For instance I have a user control that has a listview set up with gridviewcolumns, headers, and is bound to a view model. But the list view in the user control has selected item properties and such that I'd like to expose to the host without having to do something like usercontrol.customListView.property. Or is that how I should do it? I'd like to go just usercontrol.property, omitting customListView. Perhap I should just create properties in the user controls code behind that return the list view controls properties that I want attached directly to the user control?

I feel like that latter option doesn't really break MVVM since they are exposed for the host to interact with, not really related to the view itself. Any suggested would be appreciated.

EDIT: In fact, I'd really like to have a SelectedItem property directly on the user control that is not ListViewItem or object, but actually of the datatype contained that doe like:

public MyDataType SelectedItem {
    get {
        return customListView.SelectedItem as MyDataType;
    }
}

Would that be permissible in MVVM? Because I don't see how I could have that in the ViewModel, seems like it would have to be in the partial class code behind.

This is pretty common task when you want to put something repeated into UserControl . The simplest approach to do so is when you are not creating specialized ViewModel for that UserControl , but sort of making custom control (build with the use of UserControl for simplicity). End result may looks like this

<UserControl x:Class="SomeNamespace.SomeUserControl" ...>
    ...
    <TextBlock Text="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}" ...>
</UserControl>

.

public partial class SomeUserControl : UserControl
{
    // simple dependency property to bind to
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(SomeUserControl), new PropertyMetadata());

    // has some complicated logic
    public double Value
    {
        get { return (double)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(double), typeof(SomeUserControl),
        new PropertyMetadata((d, a) => ((SomeUserControl)d).ValueChanged()));
    private void ValueChanged()
    {
        ... // do something complicated here
            // e.g. create complicated dynamic animation
    }

    ...
}

Usage will looks like this in containing window

<l:SomeUserControl Text="Text" Value="{Binding SomeValue}" ... />

As you can see SomeValue is bound to Value and there is no MVVM violations.

Of course, you can create a proper ViewModel if view logic is complicated or required too much bindings and it's rather easier to allow ViewModels to communicate directly (via properties/methods).

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