无论如何将扩展方法的结果存储在原始对象中?
Is there anyway to have the result of extension method stored in the original object?
我有一个 class UserControl class(说 MyDataGrid),它继承自第 3 方 DataGrid(说 TheirDataGrid)。在这种情况下,我只创建了 MyDataGrid 控件,但没有继承自 TheirDataGridColumn 和 TheirDataGridCell
的 MyDataGridColumn 和 MyDataGridCell
我的情况是,我为 TheirDataGridColumn 创建了一些扩展方法,这将向 TheirDataGridColumn 添加一些事件处理程序(通过 += 运算符)
如果我们只调用一次扩展方法就可以了
但是如果我们多次调用扩展方法,事件的数量就会累加起来。 (在我的例子中,它仍然可以,因为它只修改了事件中的一个原语属性,最后一个事件最终会生效。但仍然想知道是否有更好的方法)。
目前我能想到的有以下几种做法:
每次调用扩展方法时清除 TheirDataGridColumn 中的所有事件处理程序。但似乎我们只能通过反射来检索非公共变量(How to remove all event handlers from an event)。另外,在上面的例子中,它是众所周知的默认 Win 按钮控件,但我使用的是第 3 方控件。
有我自己的 MyDataGridColumn class,它继承自 TheirDataGridColumn,有一个额外的变量来存储添加的事件句柄。所以,每次我调用扩展函数(实际上,在这种情况下,不需要扩展函数,因为我们可以直接在 MyDataGridColumn class 中添加函数),它可以删除事件处理程序(通过 -= handler)。
有地方可以存储添加的事件处理程序,以便以后可以将其删除。但是由于我在扩展方法中,所以我没有办法保存添加的事件处理程序,因为没有扩展属性。如果我将它保存在另一个 class 的静态级别,它是静态级别而不是实例级别。当然,我可能有一个静态级别的字典,但需要考虑一个唯一的键来标识每一列。
对于 1,这是一种很肮脏的方式。此外,它可能会无意中删除一些其他事件处理程序
对于 2,它需要很多重构,我想避免这种情况
对于3,个人来说,我更喜欢这种方式,前提是我可以找到一种方法保存添加的事件处理程序,并在下次再次调用此方法时将其删除
非常感谢任何帮助。
从 更新代码,我们可以在添加处理程序之前删除它(因为如果没有处理程序,删除不会失败):
private void UltraGrid1_InitializeLayout(object sender, InitializeLayoutEventArgs e)
{
var column = e.Layout.Bands[YOUR_BAND_INDEX].Columns[YOUR_COLUMN_INDEX];
column.Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
var editor = column.Editor as FormattedLinkEditor;
//remove the handler before add, to prevent adding multiple handlers
editor.LinkClicked -= this.Editor_LinkClicked;
editor.LinkClicked += this.Editor_LinkClicked;
}
或者我们可以使用其中一个控件的 Tag
属性来记住我们已经为此添加了一个处理程序。 Windows 表单控件有一个 Tag
属性,它是一个对象,用于存储与控件关联的通用数据。如果我们在标签中存储一个字符串并稍后检查它,我们可以避免多次添加处理程序。也许像其中之一:
private void UltraGrid1_InitializeLayout(object sender, InitializeLayoutEventArgs e)
{
var column = e.Layout.Bands[YOUR_BAND_INDEX].Columns[YOUR_COLUMN_INDEX];
//did we add the handler already?
if(column.Tag != null && column.Tag.ToString() == "handlerIsAdded")
return;
column.Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
var editor = column.Editor as FormattedLinkEditor;
editor.LinkClicked += this.Editor_LinkClicked;
column.Tag = "handlerIsAdded"; //remember for next time, so we don't add handler again
}
不知道你是在专栏级别还是在编辑级别添加这个;我从未使用过您正在使用的网格控件。如果该列只有一个编辑器控件并且没有更新,那么您也可以使用编辑器控件:
private void UltraGrid1_InitializeLayout(object sender, InitializeLayoutEventArgs e)
{
var column = e.Layout.Bands[YOUR_BAND_INDEX].Columns[YOUR_COLUMN_INDEX];
column.Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
var editor = column.Editor as FormattedLinkEditor;
//did we add the handler already?
if(editor.Tag != null && editor.Tag.ToString() == "handlerIsAdded")
return;
editor.LinkClicked += this.Editor_LinkClicked;
editor.Tag = "handlerIsAdded"; //remember for next time
}
我有一个 class UserControl class(说 MyDataGrid),它继承自第 3 方 DataGrid(说 TheirDataGrid)。在这种情况下,我只创建了 MyDataGrid 控件,但没有继承自 TheirDataGridColumn 和 TheirDataGridCell
的 MyDataGridColumn 和 MyDataGridCell我的情况是,我为 TheirDataGridColumn 创建了一些扩展方法,这将向 TheirDataGridColumn 添加一些事件处理程序(通过 += 运算符)
如果我们只调用一次扩展方法就可以了 但是如果我们多次调用扩展方法,事件的数量就会累加起来。 (在我的例子中,它仍然可以,因为它只修改了事件中的一个原语属性,最后一个事件最终会生效。但仍然想知道是否有更好的方法)。
目前我能想到的有以下几种做法:
每次调用扩展方法时清除 TheirDataGridColumn 中的所有事件处理程序。但似乎我们只能通过反射来检索非公共变量(How to remove all event handlers from an event)。另外,在上面的例子中,它是众所周知的默认 Win 按钮控件,但我使用的是第 3 方控件。
有我自己的 MyDataGridColumn class,它继承自 TheirDataGridColumn,有一个额外的变量来存储添加的事件句柄。所以,每次我调用扩展函数(实际上,在这种情况下,不需要扩展函数,因为我们可以直接在 MyDataGridColumn class 中添加函数),它可以删除事件处理程序(通过 -= handler)。
有地方可以存储添加的事件处理程序,以便以后可以将其删除。但是由于我在扩展方法中,所以我没有办法保存添加的事件处理程序,因为没有扩展属性。如果我将它保存在另一个 class 的静态级别,它是静态级别而不是实例级别。当然,我可能有一个静态级别的字典,但需要考虑一个唯一的键来标识每一列。
对于 1,这是一种很肮脏的方式。此外,它可能会无意中删除一些其他事件处理程序
对于 2,它需要很多重构,我想避免这种情况
对于3,个人来说,我更喜欢这种方式,前提是我可以找到一种方法保存添加的事件处理程序,并在下次再次调用此方法时将其删除
非常感谢任何帮助。
从
private void UltraGrid1_InitializeLayout(object sender, InitializeLayoutEventArgs e)
{
var column = e.Layout.Bands[YOUR_BAND_INDEX].Columns[YOUR_COLUMN_INDEX];
column.Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
var editor = column.Editor as FormattedLinkEditor;
//remove the handler before add, to prevent adding multiple handlers
editor.LinkClicked -= this.Editor_LinkClicked;
editor.LinkClicked += this.Editor_LinkClicked;
}
或者我们可以使用其中一个控件的 Tag
属性来记住我们已经为此添加了一个处理程序。 Windows 表单控件有一个 Tag
属性,它是一个对象,用于存储与控件关联的通用数据。如果我们在标签中存储一个字符串并稍后检查它,我们可以避免多次添加处理程序。也许像其中之一:
private void UltraGrid1_InitializeLayout(object sender, InitializeLayoutEventArgs e)
{
var column = e.Layout.Bands[YOUR_BAND_INDEX].Columns[YOUR_COLUMN_INDEX];
//did we add the handler already?
if(column.Tag != null && column.Tag.ToString() == "handlerIsAdded")
return;
column.Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
var editor = column.Editor as FormattedLinkEditor;
editor.LinkClicked += this.Editor_LinkClicked;
column.Tag = "handlerIsAdded"; //remember for next time, so we don't add handler again
}
不知道你是在专栏级别还是在编辑级别添加这个;我从未使用过您正在使用的网格控件。如果该列只有一个编辑器控件并且没有更新,那么您也可以使用编辑器控件:
private void UltraGrid1_InitializeLayout(object sender, InitializeLayoutEventArgs e)
{
var column = e.Layout.Bands[YOUR_BAND_INDEX].Columns[YOUR_COLUMN_INDEX];
column.Style = Infragistics.Win.UltraWinGrid.ColumnStyle.URL;
var editor = column.Editor as FormattedLinkEditor;
//did we add the handler already?
if(editor.Tag != null && editor.Tag.ToString() == "handlerIsAdded")
return;
editor.LinkClicked += this.Editor_LinkClicked;
editor.Tag = "handlerIsAdded"; //remember for next time
}