wpf - 列表框和 MVVM 的用户控制数据绑定(bind)问题

标签 wpf data-binding mvvm user-controls

我用 2 ListBox 创建了一个 WPF 用户控件es(命名为“Source”和“Value”)和一个“Add”按钮,允许用户“复制”绑定(bind)到 Source ListBox 的项目值 ListBox .这是代码:

public partial class MultiListSelect : UserControl
{
    public static readonly DependencyProperty ListSourceProperty;
    public static readonly DependencyProperty ListValueProperty;

    public IEnumerable ListSource  
    {
        get { return (ObservableCollection<object>)GetValue(MultiListSelect.ListSourceProperty); } 
        set { SetValue(MultiListSelect.ListSourceProperty, value); }  
    }

    public IEnumerable ListValue
    {
        get { return (ObservableCollection<object>)GetValue(MultiListSelect.ListValueProperty); }
        set { SetValue(MultiListSelect.ListValueProperty, value); }
    }  


    public MultiListSelect()
    {
        InitializeComponent();
    }

    static MultiListSelect()  
     { 

         MultiListSelect.ListSourceProperty =  
            DependencyProperty.Register("ListSource",
            typeof(IEnumerable), typeof(MultiListSelect));

         MultiListSelect.ListValueProperty =
            DependencyProperty.Register("ListValue",
            typeof(IEnumerable), typeof(MultiListSelect));

     }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        foreach (object o in listBoxSource.SelectedItems)
        {
             listBoxValue.Items.Add(o);
        }
    }

}

我使用此用户控件的 View 是使用 MVVM Light。这是我的 ViewModel 代码,它公开了绑定(bind)到每个 ListBox 的数据:
public class ProfileViewModel : ViewModelBase
{
    public User User { get; set; }

    // This gets bound to the Source listbox
    private ObservableCollection<OperatingArea> _operatingAreas;
    public ObservableCollection<OperatingArea> OperatingAreas 
    { 
        get { return _operatingAreas; }
        private set
        {
            _operatingAreas = value;
        }
    }

    public ProfileViewModel()
    {
        OperatingAreas = _rpDomain.LoadOperatingAreas();
        WindowsIdentity identity = WindowsIdentity.GetCurrent();

        if (User == null)
        {
            User = _rpDomain.CreateUser();
            User.Preferences = _rpDomain.CreateUserPreferences();
            User.UserId = identity.Name;

            _rpDomain.Add(User);
        }

        if (User.Preferences == null)
        {
            User.Preferences = _rpDomain.CreateUserPreferences();
        }

        if (User.Preferences.ViewableOperatingAreas == null)
        {
            // This gets bound to my 'Value' ListBox
            User.Preferences.ViewableOperatingAreas = new ObservableCollection<OperatingArea>();
        }
    }
}

绑定(bind)工作正常。问题是,当用户在“源”列表框中选择项目并单击“添加”按钮时,当此行在 btnAdd_Click 事件处理程序的用户控件后面的代码中执行时,我得到一个错误:
listBoxValue.Items.Add(o);

我收到的错误是:“使用 ItemSource 时操作无效。改为使用 ItemsControl.ItemsSource 访问和修改元素。所以,我理解这个问题,但我不知道解决这个问题的最佳方法。 DependencyProperties 是 IEnumerable 类型的,所以我不能直接在用户控件后面的代码中添加它们。此外,我无法访问 ViewModel 并直接更新属性,因为用户控件库无法为 View 引用 ViewModel。将项目从“源”列表框复制到“值”列表框的最佳方法是什么(最好将代码包含在用户控件中,而不是要求 View/ViewModel 添加项目)。此外,这是一个用户控件,因此绑定(bind)到每个列表框的类型随控件的每次使用而变化。

编辑 - 2011 年 10 月 4 日

所以,真正的问题是如何从我的用户控件中更新(添加到)“值”列表?依赖属性是 IEnumerable 类型的,所以不能直接更新,而且如上面的错误所示,我不能简单地调用 listbox.items.Add()。我正在使用 MVVM,因此需要对 ViewModel 中公开的属性进行数据绑定(bind)。此外,用户控件不知道(也不应该知道)在运行时绑定(bind)到它的类型。我意识到我的用户控件可以引发可以通过 MVVM Light 中的 EventToCommand 功能处理的“已添加”事件,但这似乎没有必要 - 如果我从需要我的第 3 方控件供应商处购买控件,我个人不会满意自己更新收藏。我知道这是可能的,因为这本质上是组合框的工作方式 - 组合框同时具有 ItemsSource 属性和 SelectedValue 属性,它们可以绑定(bind)到 ViewModel 上的属性。
<ComboBox 
    ItemsSource="{Binding Path=Categories}"
    DisplayMemberPath="Name"
    SelectedValue="{Binding Path=SelectedCategory, Mode=TwoWay}"/> 

最佳答案

ItemsItemsSource是互斥的,一次ItemsSource设置为 Items.Add(..)会扔。不要使用 ItemsSource即使它是最简单的选项,请使用 Items.Add在循环中(您可以从 DP 值更改事件处理程序中调用它)。

如果您需要任何进一步的帮助,请告诉我。

关于wpf - 列表框和 MVVM 的用户控制数据绑定(bind)问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7640866/

相关文章:

c# - 两个 View 模型之间的主从拆分 : Where to put cancel command logic?

c# - 如何使用 WPF 数据绑定(bind)来编辑多个项目的公共(public)字段

java - Spring Boot 表单数据与 FreeMarker 绑定(bind)列表

c# - 在 Xamarin.Forms 项目中实现 MVVM

wpf - 在 WPF 弹出消息中,下拉列表出现在主窗口后面

javascript - Angular js - 绑定(bind)到函数

c# - 当只有显式更改的行应该被更改时,datagrid 中的多行正在更改

c# - 无论鼠标在哪里,如何访问 WPF 中的鼠标移动事件?

wpf - IsDefault 和 IsDefaulted 按钮有什么区别?

wpf - 提高 StackPanel 中巨大列表框的性能?