将项添加到未知类型的ObservableCollection

时间:2010-01-11 07:33:44

标签: c# wpf reflection mvvm observablecollection

我正在使用MVVM设计模式创建一个WPF应用程序,我正在尝试创建一个Combobox,允许用户在运行时编辑下拉列表中的项目,类似于MS Access 2007的方式你来弄吧。所以我创建了一个构建在Combobox之上的UserControl ...当显示下拉列表时,列表下方有一个按钮,打开另一个窗口来编辑列表中的项目。很简单,但弹出窗口对列表中的项目类型一无所知,除了它们是某种类型的ObservableCollection。

您可以查看我正在尝试解释的内容的屏幕截图HERE

例如,在View上,我将自定义组合框绑定到ObservableCollection<Sizes>。我单击按钮编辑列表,弹出窗口显示TextBox中的所有项目供用户编辑。问题是尝试从弹出窗口添加/更新/删除ObservableCollection中的项目。除了显示字段的名称(this.DisplayMemberPath)之外,此窗口对ObservableCollection一无所知。

我知道我总是可以将组合框绑定到ObservableCollection<string>IEnumerable<string>,但是我使用LINQ to SQL来填充组合框项目,我需要知道更改跟踪所有我的对象,所以我可以更新数据库对列表所做的更改。因此,(我认为)我必须使用ObservableCollection<Sizes>来监控变更跟踪。我也玩弄了使用CollectionChanged事件更新数据库的想法,但我想知道是否有更清洁的方法。

我有一种感觉,我需要使用Reflection来更新列表,但我不太熟悉使用Reflection。

这是我显示弹出窗口的源代码:

public event EventHandler<EventArgs> EditListClick;
private void EditButton_Click(object sender, RoutedEventArgs e)
{
    if (this.EditListDialog == null)
    {
        // Create the default dialog window for editing the list
        EditListDialogWindow dialog = new EditListDialogWindow();
        string items = string.Empty;

        if (this.Items != null)
        {
            // Loop through each item and flatten the list
            foreach (object item in this.Items)
            {
                PropertyInfo pi = item.GetType().GetProperty(this.DisplayMemberPath);
                string value = pi.GetValue(item, null) as string;

                items = string.Concat(items, ((items == string.Empty) ? items : "\n") + value);
            }

            // Now pass the information to the dialog window
            dialog.TextList = items;
        }

        // Set the owner and display the dialog
        dialog.Owner = Window.GetWindow(this);
        dialog.ShowDialog();

        // If the user has pressed the OK button...
        if (dialog.DialogResult.HasValue && dialog.DialogResult.Value)
        {
            // Make sure there has been a change
            if (items != dialog.TextList)
            {
                // Unflatten the string into an Array
                string[] itemArray = dialog.TextList.Split(new string[]{"\n", "\r"}, StringSplitOptions.RemoveEmptyEntries);

                // Add the items to the list
                foreach (string item in itemArray)
                {
                    // This is where I run into problems...
                    // Should I be using reflection here??
                    ((ObservableCollection<object>)this.ItemsSource).Add(item.Trim());
                }
            }
        }
    }

    if (EditListClick != null)
        EditListClick(this, EventArgs.Empty);
}

2 个答案:

答案 0 :(得分:2)

听起来你需要知道列表,但不是特定的类型。这就是非通用接口的用武之地;尝试以IList(包含所有索引器/添加/删除等),INotifyCollectionChanged(用于通知)等方式访问列表。

在更一般的情况下,还有IBindingList / IBindingListView / ITypedList等,但我认为在这种情况下你不需要那些。

答案 1 :(得分:0)

您是否尝试使用IValueConverter

将ObservbleCollection绑定到自定义ComboBox时,请设置自定义IValueConverter。他定义了两种方法,ConvertConvertBack。这个想法是,你可以转换类型。

在这种情况下,您可以拥有ObservableCollection<Sizes>,然后绑定转换器会将其转换为所需类型。

如果您将转换器设置在集合绑定上,则可以转换为ObservableCollection<Sizes>ObservableCollection<string>

另一个选项是将IValueConverter内部设置为自定义ComboBox,并执行从Sizesstring的转换。另一个选项是特定的itemtemplate包含绑定和转换。

HTH。