2011-10-03 71 views
1

我已经创建了2个ListBox ES一个WPF用户控件(命名为“源”和“价值”)和“添加”按钮,允许用户以“复制”的项目,是绑定到源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); 
     } 
    } 

} 

我的看法,消耗此用户控件使用MVVM光。这里是我的ViewModel代码暴露了被绑定到每个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>(); 
     } 
    } 
} 

工作没关系的结合。问题是,当用户选择“源”列表框中的项目并单击“添加”按钮时,在btnAdd_Click事件处理程序中的用户控件背后的代码中执行此行时出现错误:

listBoxValue.Items.Add(o); 

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

编辑 - 2011年10月4日

所以,真正的问题是如何做我更新(添加)“值”列表从我的用户控件中?依赖属性是IEnumerable类型的,所以它不能直接更新,并且如上面的错误所示,我不能简单地调用listbox.items.Add()。我正在使用MVVM,因此数据绑定到ViewModel中公开的属性是必需的。用户控件也不知道(也不应该知道)在运行时绑定到的类型。我意识到我的用户控件可能会引发一个可以通过MVVM Light中的EventToCommand功能处理的“已添加”事件,但似乎没有必要 - 如果我从第三方控制供应商那里购买了需要我的控件,我个人不会满意自己更新集合。我知道这是可能的,因为这实际上是组合框的工作方式 - 组合框同时具有可以绑定到ViewModel属性的ItemsSource属性和SelectedValue属性。

<ComboBox 
    ItemsSource="{Binding Path=Categories}" 
    DisplayMemberPath="Name" 
    SelectedValue="{Binding Path=SelectedCategory, Mode=TwoWay}"/> 

回答

0

ItemsItemsSource是相互排斥的,一旦ItemsSource设置的东西,Items.Add(..)将抛出。即使它是最简单的选项,也不要使用ItemsSource,在循环内使用Items.Add(可以在DP值更改的事件处理程序中调用它)。

请让我知道如果你需要任何进一步的帮助。

+0

如果我按照你的建议去做,我怎么看不到在视图模型绑定属性(收集)被添加到值列表框中的新项目进行更新。我错过了什么吗? –

+0

嗨,你是对的 - 责任将落在你身上。 – 2011-10-04 08:10:44

+0

好吧,但是如何从我的用户控件中更新依赖项属性(IEnumerable)? IEnumerable旨在为只读。 –