2012-11-06 29 views
0

在ObjectListView控制的演示有这样的代码(在“复杂的例子”标签页),以允许自定义编辑器(组合框)(适应于我的情况和编辑的清晰度):Winforms控件和“通用”事件处理程序。我怎样才能做到这一点?

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)获取SomeObject。属性NAME不同。

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

类型变化太多,但我可以用通用的方法用不那么“类型安全” API相结合(例如,所述cb.DataBindings.Add和cb.DataSource都使用一个object

覆盖的那些情况下

反思?更多lambdas?有任何想法吗?任何其他方式来做同样的事情?

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#有类似的东西。

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

+1

所以你想创建一个签名'ObjectListView_CellEditStarting (TSomeType senderColumn,CellEditEventArgs e)'?另外,你可能想用答案来标记你的其他一些问题。 – Tejs

+1

那么,我的问题的其他组成部分呢?上述方法签名是你想要实现的吗? – Tejs

+0

让我试试...我会在以后回复你:-) –

回答

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内部)的设置之间的断开。

但是,考虑到所有事情,它要比复制粘贴相同代码的代码要好得多。

相关问题