ObjectListViewコントロールのデモには、カスタムエディター(ComboBox)を使用できるようにするための次のコード([複雑な例]タブページ)があります(私の場合に適合し、わかりやすくするために編集しました)。
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
)
反射?より多くのラムダ?何か案は?同じことをする他の方法はありますか?
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は、実際のパラメータではありませんが、私が何を求めているかはわかります。同じコードスケルトンを何度も繰り返さないようにしたい。
1つの解決策は、CのDEFINEのような「プリプロセッサジェネリック」ですが、c#にそのようなものがあるとは思いません。
それで、誰かがこれを解決するためのいくつかの代替案を持っていますか?