0

在 ObjectListView 控件的演示中有此代码(在“复杂示例”选项卡页面中)允许自定义编辑器(组合框)(适应我的情况并为清晰起见进行了编辑):

EventHandler CurrentEH;
private void ObjectListView_CellEditStarting(object sender,
                                             CellEditEventArgs e)
{
    if (e.Column == SomeCol)
    {
        ISomeInterface M = (e.RowObject as ObjectListView1Row).SomeObject; //(1)
        ComboBox cb = new ComboBox();
        cb.Bounds = e.CellBounds;
        cb.DropDownStyle = ComboBoxStyle.DropDownList;
        cb.DataSource = ISomeOtherObjectCollection;
        cb.DisplayMember = "propertyName";
        cb.DataBindings.Add("SelectedItem", 
                            M, "ISomeOtherObject", false,
                            DataSourceUpdateMode.Never);
        e.Control = cb;
        cb.SelectedIndexChanged += 
            CurrentEH = (object sender2, EventArgs e2) =>
                M.ISomeOtherObject = 
                    (ISomeOtherObject)((ComboBox)sender2).SelectedValue;   //(2)
    }
}

private void ObjectListView_CellEditFinishing(object sender,
                                               CellEditEventArgs e)
{
    if (e.Column == SomeCol)
    {
        // Stop listening for change events
        ((ComboBox)e.Control).SelectedIndexChanged -= CurrentEH;
        // Any updating will have been down in the SelectedIndexChanged
        // event handler.
        // Here we simply make the list redraw the involved ListViewItem
        ((ObjectListView)sender).RefreshItem(e.ListViewItem);
        // We have updated the model object, so we cancel the auto update
        e.Cancel = true;
    }
}

我在 objectlistviews 中有太多其他带有组合编辑器的列,无法使用复制和粘贴策略(此外,复制和粘贴是严重的错误来源),因此我尝试对代码进行参数化以将代码重复降至最低。ObjectListView_CellEditFinishing 是小菜一碟:

HashSet<OLVColumn> cbColumns = new HashSet<OLVColumn> (new OLVColumn[] { SomeCol, SomeCol2, ...};

private void ObjectListView_CellEditFinishing(object sender,
                                               CellEditEventArgs e)
{
    if (cbColumns.Contains(e.Column)) ...

但 ObjectListView_CellEditStarting 是有问题的。

我想在 CellEditStarting 中我将不得不分别区分每种情况:

private void ObjectListView_CellEditStarting(object sender,
                                             CellEditEventArgs e)
{
    if (e.Column == SomeCol)
        // code to create the combo, put the correct list as the datasource, etc.
    else if (e.Column == SomeOtherCol)  
        // code to create the combo, put the correct list as the datasource, etc.

等等。

但是如何参数化“创建组合的代码,将正确的列表作为数据源等”?问题线是

(1) 获取一些对象。属性名称各不相同。

(2) 设置ISomeOtherObject,属性名也不同。

类型也各不相同,但我可以使用通用方法结合不太“类型安全”的 API 来涵盖这些情况(例如,cb.DataBindings.Add 和 cb.DataSource 都使用object

反射?更多的lambda?有任何想法吗?还有其他方法可以做到这一点吗?

PS:我希望能够做这样的事情:

private void ObjectListView_CellEditStarting(object sender,
                                             CellEditEventArgs e)
{
    if (e.Column == SomeCol)
        SetUpCombo<ISomeInterface>(ISomeOtherObjectCollection,
                                   "propertyName",
                                   SomeObject,
                                   ISomeOtherObject);

    else if (e.Column == SomeOtherCol)  
        SetUpCombo<ISomeInterface2>(ISomeOtherObject2Collection,
                                   "propertyName2",
                                   SomeObject2
                                   ISomeOtherObject2);

等等。或类似的东西。

我知道,参数 SomeObject 和 ISomeOtherObject 不是真正的参数,但你明白我想要什么。我不想一次又一次地重复相同的代码框架。

一种解决方案是像 C 的 DEFINE 这样的“预处理器泛型”,但我不认为 c# 有这样的东西。

那么,有没有人有一些替代的想法来解决这个问题?

4

1 回答 1

0

找到了。向 Tejs 致敬!

private void SetUpCombo(CellEditEventArgs e, 
                        object ComboItems, string DisplayMember,
                        object DataSource, string PropertyName,
                        EventHandler evt)
{
    ComboBox cb = new ComboBox();
    cb.Bounds = e.CellBounds;
    cb.DropDownStyle = ComboBoxStyle.DropDownList;
    cb.DataSource = ComboItems;
    cb.DisplayMember = DisplayMember;
    cb.DataBindings.Add("SelectedItem", DataSource, PropertyName,
                            false, DataSourceUpdateMode.Never);
    e.Control = cb;
    cb.SelectedIndexChanged += CurrentEH = evt;
}

和重写的 CellEditStarting:

private void ObjectListView_CellEditStarting(object sender,
                                             CellEditEventArgs e)
{
    if (e.Column == SomeCol)
    {
        ISomeInterface M = (e.RowObject as ObjectListView1Row).SomeObject; 
        SetUpCombo(e, 
                   ISomeOtherObjectCollection,"propertyName",
                   M, "ISomeOtherObject",
                   (sender2, e2) =>
                       M.ISomeOtherObject = 
                           (ISomeOtherObject)((ComboBox)sender2).SelectedValue);
    }
    else if (e.Column == SomeOtherCol)  
    {
        ISomeInterface2 M = (e.RowObject as ObjectListView1Row).SomeObject2; 
        SetUpCombo(e, 
                   ISomeOtherObjectCollection2,"propertyName2",
                   M, "ISomeOtherObject2",
                   (sender2, e2) =>
                       M.ISomeOtherObject2 = 
                           (ISomeOtherObject)((ComboBox)sender2).SelectedValue);
    }

等等……有些东西我还不喜欢。例如:M.ISomeOtherObject(方法调用外)、“ISomeOtherObject”(参数)和 M.ISomeOtherObject 的设置(lambda 内)之间的断开。

但是,考虑到所有因素,它比一遍又一遍地复制和粘贴相同的代码要好得多)。

于 2012-11-07T16:58:24.293 回答