如何使我的WPF用户控件的依赖项属性更新我的视图模型?

时间:2021-07-21 07:27:02

I'm trying to create a user control with dependency properties to bind to. Internally I have a ComboBox that is bound to these same properties, but the binding only works one way. The ComboBox fills from the ItemsSource, but SelectedItem doesn't get updated back to the viewmodel I'm binding to.

我正在尝试创建一个具有要绑定的依赖项属性的用户控件。在内部我有一个绑定到这些相同属性的ComboBox,但绑定只能以一种方式工作。 ComboBox从ItemsSource填充,但SelectedItem不会更新回我绑定的viewmodel。

A simplified example:

一个简化的例子:

This is the view model to bind with the user control:

这是与用户控件绑定的视图模型:

public class PeopleViewModel : INotifyPropertyChanged
{
    public PeopleViewModel()
    {
        People = new List<string>( new [] {"John", "Alfred","Dave"});
        SelectedPerson = People.FirstOrDefault();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private IEnumerable<string> _people;
    public IEnumerable<string> People 
    { 
        get { return _people; } 
        set
        {
            _people = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("People"));
            }
        }
    }

    private string _selectedPerson;
    public string SelectedPerson 
    {
        get { return _selectedPerson; }
        set 
        { 
            _selectedPerson = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("SelectedPerson"));
            }
        } 
    }
}

This is the User control:

这是用户控件:

<UserControl x:Class="PeopleControlTest.PeopleControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" d:DesignHeight="56" d:DesignWidth="637">
<StackPanel >
    <ComboBox Margin="11"
              ItemsSource="{Binding BoundPeople, RelativeSource={RelativeSource AncestorType=UserControl}}"
              SelectedItem="{Binding BoundSelectedPerson, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</StackPanel>

with code behind

代码背后

public partial class PeopleControl : UserControl
{
    public PeopleControl()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty BoundPeopleProperty =
        DependencyProperty.Register("BoundPeople", typeof(IEnumerable<string>), typeof(PeopleControl), new UIPropertyMetadata(null));

    public static readonly DependencyProperty BoundSelectedPersonProperty =
        DependencyProperty.Register("BoundSelectedPerson", typeof(string), typeof(PeopleControl), new UIPropertyMetadata(""));

    public IEnumerable<string> BoundPeople
    {
        get { return (IEnumerable<string>)GetValue(BoundPeopleProperty); }
        set { SetValue(BoundPeopleProperty, value); }
    }

    public string BoundSelectedPerson
    {
        get { return (string)GetValue(BoundSelectedPersonProperty); }
        set { SetValue(BoundSelectedPersonProperty, value); }
    }
}

And this is how I bind the user control in the main window (with the windows data context set to an instance of the viewmodel)

这就是我在主窗口中绑定用户控件的方式(将windows数据上下文设置为viewmodel的一个实例)

<Window x:Class="PeopleControlTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:controls="clr-namespace:PeopleControlTest"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <controls:PeopleControl 
            BoundPeople="{Binding People}" 
            BoundSelectedPerson="{Binding SelectedPerson}"/>
    </Grid>
</Window>

The combobox in the user control fills with the names, but when I select a different name this doesn't get updated back to the view model. Any idea what I'm missing here?

用户控件中的组合框填充了名称,但是当我选择不同的名称时,这不会更新回到视图模型。知道我在这里缺少什么吗?

Thanks!

谢谢!

1 个解决方案

#1


19  

Some properties bind two-way by default (Including SelectedItem) but your BoundSelectedPerson does not. You can set the Mode of the binding:

默认情况下,某些属性绑定为双向(包括SelectedItem),但您的BoundSelectedPerson不绑定。您可以设置绑定模式:

   <controls:PeopleControl 
            BoundPeople="{Binding People}" 
            BoundSelectedPerson="{Binding SelectedPerson, Mode=TwoWay}"/>

Or you can make it TwoWay by default by setting a flag on the DependencyProperty:

或者,您可以通过在DependencyProperty上设置标志来默认为TwoWay:

    public static readonly DependencyProperty BoundSelectedPersonProperty =
        DependencyProperty.Register("BoundSelectedPerson", typeof(string), typeof(PeopleControl), new FrameworkPropertyMetadata("",FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

#1


19  

Some properties bind two-way by default (Including SelectedItem) but your BoundSelectedPerson does not. You can set the Mode of the binding:

默认情况下,某些属性绑定为双向(包括SelectedItem),但您的BoundSelectedPerson不绑定。您可以设置绑定模式:

   <controls:PeopleControl 
            BoundPeople="{Binding People}" 
            BoundSelectedPerson="{Binding SelectedPerson, Mode=TwoWay}"/>

Or you can make it TwoWay by default by setting a flag on the DependencyProperty:

或者,您可以通过在DependencyProperty上设置标志来默认为TwoWay:

    public static readonly DependencyProperty BoundSelectedPersonProperty =
        DependencyProperty.Register("BoundSelectedPerson", typeof(string), typeof(PeopleControl), new FrameworkPropertyMetadata("",FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));