1

我正在使用 Microsoft.win32.OpenFileDialog 打开 SQLCE 数据库文件 (.sdf)。我添加了以下过滤器 *.sdf,因此它只显示 .sdf 文件,但我还要求它从对话窗口中删除特定的 .sdf 文件。我要删除的数据库的名称是固定的,但我无法控制其他数据库的名称,因为它们是通过应用程序创建的,并且用户可以通过应用程序决定他们想要命名它们的名称。

我想要实现的一个例子是,假设我有以下数据库

数据库1.sdf 数据库2.sdf 数据库3.sdf

我想获取除 database2.sdf 之外的所有内容

任何帮助将不胜感激

4

2 回答 2

1

OFD 很棘手。它是一个通用的文件选择器,旨在“尽可能有用”——用于文件。过滤器只是用户的小帮手。他们不会阻止选择其他文件。

运行画笔或您的应用程序,打开文件选择器。在文件类型组合框中,您可能会看到一些过滤器,实际上对话框只会显示该文件。输入“*”作为文件名,然后按 OK/Enter。几乎可以肯定,现在无论过滤器如何,都会看到所有文件。

这种行为适合您使用吗?如果您想从该对话框中隐藏某些文件,我认为不是。如果我是对的,那么 OFD 根本不适合你,你应该编写自己的简单“SDF 数据库选择器”,构建一个 ListView/etc,它只会列出你想要显示的内容。

否则,如果这没问题,那么您可以将 HANDLE(在 .Net 中它们作为 传递IntPtr)到窗口,然后检查窗口结构以在其上找到 (IIRC) SysListView 控件,然后与它交谈以删除不需要的元素。所有工作都将由 C++ 或 P/Invoke 完成。如果您真的需要它,我会尝试找到一些链接。给我留个便条。

--
对于初学者,很抱歉输入错误的组件名称。窗口类是SysListView32.

首先,浏览一些文章。要小心,因为大多数时候指的是 System.Windows.Forms,而不是 WPF。大多数信息都是正确且相关的,因为在内部,它仍然是同一个组件,只是包装有点不同。

一旦你成功拦截了打开窗口的动作,并且你得到了SHELLDLL_DefView/SysListView32控件的HANDLE(IntPtr),你就可以开始玩真正的游戏了。

该控件尽管名称为“SysListView32”,但实际上命名为“ListView”,并且来自几乎与 Windows 本身一样古老的 comctl32.dll。您可以通过向控件发送“原始 winapi 消息”来轻松地动态重新配置控件,但丑陋的是,在 .Net 中没有漂亮的方法可以做到这一点。您必须 P/Invoke 到SendMessage ,所以也可以在MSDN上阅读有关该功能的信息。它的第一个参数就是您刚刚找到HWNDHANDLE(IntPtr) (HWND = [H]andle-to-[W]i[ND]ow)。

名为“ListView”的控件可以理解很多不同的消息。该控件是一个窗口,因此它可以理解 WM_xxxx 消息([W]indow[M]essage_xxx)。并且还理解 blahblahblah,更重要的是,它还以 LVM_xxxx 消息 ([L]ist[V]iew[M]essage_xxxx) 的形式定义了自己的 API,例如LVM_GETITEM。请注意,在 LVM_GETITEM 页面上还有大量其他 LVM_xxx 消息:GETITEMCOUNT、INSERITEM、DELETEITEM 等。LVM_DELETEITEM 是实现目标的关键之一。这是VB中的一个例子关于如何删除“第三行中的项目”。一行,因为 ListView 的自然视图是基于网格/行的。类似桌面的显示模式是一个补充,每个项目在逻辑上仍然被认为是在连续的行中,而不是在 XY 网格单元上。好吧,好吧,除了 DESKTOP 和自由形式的图标放置,这也是由 SysListView32 完成的,但那是另一回事了..

这是一组关于 ListViews 的不错的文章:http: //msdn.microsoft.com/en-us/library/windows/desktop/bb774737 (v=vs.85).aspx 请注意,您必须将所有内容都翻译成 C#和 P/Invoke。

本机控件名为 ListView,实际上,[System.Windows.Forms.ListView] 是它的 .Net 包装器!但是,没有很好的方法将该类的实例绑定到预先存在的本机组件实例。该类旨在从头开始创建一个新的本机 ListView 组件。如果您有谷歌搜索的技巧或运气,您可以尝试将此类 ListView 绑定到本机 Listview,然后您将跳过一些 P/Invoke 麻烦,但我认为这并不值得。

手动驱动/修补/hotifxing 控件甚至更复杂一些,例如,您有时可能不得不踢它们以记住它们以在更改后更新屏幕:http: //www.codeproject.com/Questions/181852/ListView- LVM_DELETEITEM 消息后损坏. 更重要的是,过滤项目不是一次性的工作。当用户在文件夹树中上下导航时,您必须一次又一次地过滤它们。当用户显示另一个文件夹的一些新内容时,您必须找到一种方法来获得通知。幸运的是,每个使用 LVM 的人都必然会使用与您现在使用的 API 相同的 API。这意味着文件对话框必须向控件发送一系列 LVI_DELETExxx/LVI_INSERTxxx 消息,并且您可能会尝试拦截+检查+过滤掉它们,因此“坏项目”将在放置项目时被即时踢出清单..这是我关于如何“轻松”做到这一点的建议。

我希望这可以帮助您解决问题。总的来说,除非您使用过原生控件和 P/Invoke 几次,否则这并不容易。我只鼓励你重新考虑你的问题:真的不能通过简单的文件名验证加上一个消息框“对不起,你不能使用这个文件”来解决吗?这将容易几个数量级..

很抱歉,我找不到任何完整/准确的代码来获取句柄以及读取和删除项目。我知道几年前我见过这样的例子,但现在我找不到了进一步解决这个问题。

于 2012-08-13T08:45:06.453 回答
0

您将遇到的一个问题是,即使文件可以隐藏在文件浏览器中,用户仍然可以在对话框的文本部分输入文件名。该文件确实存在,因此就对话框而言,它将是一个有效的选择,并且该行为将难以覆盖。

您不能轻易强制对话框不选择确实存在的文件,但您可以轻松验证对话框返回的数据。我建议您在对话框关闭后验证文件名,并做出适当的反应。

于 2012-08-13T08:38:06.727 回答