Winforms ObjectListView:内部OLVColumn实例Name属性为空字符串,因此我无法按名称显示/



此问题是以下问题的一个分支:本地化ObjectListView OLVColumn,由于Empty Name属性而不可能

为了简单起见,假设我的ObjectListView包含汽车信息。用户A希望只显示"生成"列和"模型"列。用户B只想显示"型号"one_answers"年份"列。这些首选项将保存到用户本地计算机上的.ini文件中/从该文件加载。

我无法循环遍历ObjectListView的列并执行if (col.Name == colNameFromIni) { col.Visible == true; },因为每列的.Name属性都是空字符串("(,并且不会序列化到设计器代码绑定文件。任何其他Winforms控件(Label、Button等(都不会发生这种情况。它们总是将其.Name写入设计器代码绑定。

从某种意义上说,这是Winforms本身的一个缺陷,因为OLVColumn继承自System.Windows.Forms.ColumnHeader,而传统的ListView也有同样的问题。对于所有列,.Name始终为空字符串。

我想修补ObjectListView.dll的本地版本,以强制填充.Name属性,但我不知道Winforms是如何自动知道表单上每个控件的名称的。它不知何故(?(知道OLVColumn对象的名称,因为它可以在编辑列中显示它们对话框。我也有点不清楚最好的地方是在哪里插上这个。

(是的,根据顶部的链接问题,我知道作为最后的手段,我可以为源代码中的所有列硬编码colXX.Name = "colXX";,但未来添加的列可能会被忽视,因此更倾向于使用编程解决方案。(

(另请参见:https://sourceforge.net/p/objectlistview/bugs/160/:ObjectListView的作者将其声明为wont-fix,所以我想这取决于我(或我们(。(

正如您所指出的,这不是ObjectListView的错误,而是底层组件的错误。还有一个至少从2008年开始就存在的bug!因此,我怀疑它是否会被女士修复

实际上,这是设计器中自动生成代码的问题。

如果您查看按钮等其他组件,则自动生成的代码会添加这样的名称;

// 
// button2
// 
this.button2.Location = new System.Drawing.Point(458, 199);
this.button2.Name = "button2";
...

但对于ColumnHeader(Listview(和OLVColumn(ObjectListView(,则不会完成此操作,因此最终会出现此情况。

// 
// olvColumn1
// 
this.olvColumn1.AspectName = "Name";
this.olvColumn1.Text = "Name";

如果手动添加行

this.olvColumn1.Text = "olvColumn1";

然后;"问题";解决。

当然,您不能这样做,因为当您进行任何更改时,设计器将覆盖自动生成的代码,然后您将丢失这些手动添加的行。它也是不可持续的。

所以我担心你需要用某种丑陋的解决方案来解决这个问题。一些选项包括:

  1. 使用标签存储名称并与之进行比较
  2. 使用文本而不是名称(如果您有多个语言支持!(
  3. 在构造函数中手动对名称列进行编码
  4. 将文本设置为类似于";ColName;ColText";然后在你的代码将这些分开

我过去做过选项3,但只有我在维护代码,所以这很容易。

要确保没有差异,可以在构造函数中添加一个检查,将实际列数与期望的列数(硬编码(进行比较,如果不匹配,则抛出异常。此外,这不是最好的,而是另一种突出显示和减少错误的方法。

解决方法是通过反射获取OLV列,并在运行时设置其列的Name属性。每个OLV列都是一个表单级字段,所以只需从GetFields()返回的列表中选择它们即可。

Dim allFieldInfos As FieldInfo() = GetType(FrmMain).GetFields(BindingFlags.NonPublic or BindingFlags.Instance)      
For Each fi As FieldInfo In allFieldInfos
If fi.FieldType Is GetType(OLVColumn) Then
Dim instance As OLVColumn = fi.GetValue(Me)
For Each col As OLVColumn In fdlvMain.AllColumns
If ReferenceEquals(col, instance) Then
col.Name = fi.Name
End If
Next
End If
Next

最新更新