在C#程序中保存UI的状态

时间:2013-10-24 22:20:35

标签: c# .net

如何监控集合成员(界面:System.Collections.ICollection)何时发生变化?我正在尝试在System.Windows.Forms.ListView.Columns中保存列的顺序。

我为public event ColumnReorderedEventHandler ColumnReordered;

创建了一个委托
this.MyListView.ColumnReordered += new System.Windows.Forms.ColumnReorderedEventHandler(ColumnReordered);

当我的班级被召唤时:

public void ColumnReordered(object sender, EventArgs e)
{
    ListView.ColumnHeaderCollection chc = sender as ListView.ColumnHeaderCollection;
    ColumnReorderedEvemtArgs crea = e as ColumnReorderedEventArgs;
    if ((chc == null) || (crea == null)) return;

    // Prints expected values.
    Console.WriteLine("{0} -> {1}", crea.OldDisplayIndex, crea.NewDisplayIndex);

    // Prints previous state; NOT current state.
    for (int k = 0; k < chc.Count; k++)
    {
        ColumnHeader columnHeader = chc[k] as ColumnHeader;
        if (columnHeader == null)
            break;

        Console.WriteLine("{0}", columnHeader.DisplayIndex);
    }
}

这让我相信这不是我想保存状态的地方,因为更改尚未反映在返回的对象(sender)中。当用户操作列时,如何立即保存列的顺序?

1 个答案:

答案 0 :(得分:0)

我做了一些研究和一些测试。列表视图的列部分是一个名为 SysHeader32 的单独窗口句柄。

当列的顺序发生变化时,标题句柄会收到一条HDM_SETORDERARRAY消息:

http://msdn.microsoft.com/en-us/library/windows/desktop/bb775369(v=vs.85).aspx

其中 lParam 包含指向包含列的修改顺序的数组的指针。例如,当您有三列时,如果没有更改任何内容,则数组会这样:

int[] indexes = { 0, 1, 2 };

当我切换前两列时,数组如下所示:

int[] indexes = { 1, 0, 2 };

然后,您可以使用存储在数组中的索引来遍历数组以从列表视图控件中检索列。

因此,换句话说,您必须找到标题的句柄,然后设置 WndProc 来拦截传入的Windows消息,然后检测是否收到了HDM_SETORDERARRAY。如果是,请阅读 lParam 的值。

您可以使用 EnumChildWindows 通过句柄的子句柄来填充/搜索:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633494(v=vs.85).aspx

要设置挂钩,要拦截标头句柄的消息,请参阅以下堆栈溢出问题:

How do I intercept messages being sent to a window?

注意,索引已经更新时会收到HDM_SETORDERARRAY。