【问题标题】:How to make Control work for Forms?如何使控件适用于表单?
【发布时间】:2015-06-26 12:07:26
【问题描述】:

我在 WPF 中为我们的小团队制作了一个可重用的控件:一个简单的对话框,我们经常使用它。 窗口的处理是在私有方法中完成的:

private static void ExecuteInternal(
        Window owner,
        string windowTitle,
        string label,
        object operation,
        MyDialogSettings settings)
    {
        MyDialog dialog = new MyDialog(windowTitle, settings);
        dialog.Owner = owner;
        dialog.Label = label;

        ShowDialog();
    }

公共调用有一个System.Windows.Window 作为参数(--> WPF 窗口),我的函数将Owner 设置为这个窗口。 现在我的同事想从 Windows 窗体应用程序中使用这个窗口。

我的第一个想法是用表单重载公共函数调用,然后在内部使用WindowInteropHelper 处理它(参见:http://blogs.msdn.com/b/mhendersblog/archive/2005/10/04/476921.aspx

但是我必须在使用我的库的每个 (WPF) 项目中引用 Windows.Forms。 因为我无法从 WindowInteropHelper 外部访问窗口实例,所以无法在 Forms 应用程序中完成。

有什么想法吗?

【问题讨论】:

  • 保留 wpf 库。休息是你同事的问题:他想要在 winforms 中休息,他自己做 WindowInteropHelper 魔术。
  • 但是他需要引用我的 WPF 窗口 (MyDialog)。这是无法访问的,因为它在私有方法中。所以他不能使用WindowInteropHelper
  • 这是为什么呢?只要给他窗口实例。那有什么问题?如果它对 wpf 同事来说是一个大秘密,请使其非常安全(通过需要密码的公共方法大声笑)。
  • 嗯...没那么容易...这是一个对话框,在调用静态函数时弹出,在操作完成后自行关闭(如进度对话框)。所以没有机会获取window的实例(不是在调用Execute之前)
  • 您可以以某种方式报告进度,并使您漂亮的 wpf 窗口成为可选的。然后 winforms-guy 可以画出他自己丑陋的 winforms 进度对话框。

标签: c# wpf winforms


【解决方案1】:

我看到这种方法的问题是可重用控件根本不可重用。正如您所注意到的,主要方法使用 WPF-only 类型,不能在其他任何地方使用,因此现在无法在 WinForms 上重用。

为此,您需要将对话窗口的主要逻辑和视觉效果提取到用户控件中(以便它可以托管在 WinForms 中)。这是我要做的第一件事:

<UserControl .......>
    <Grid>
        <!-- Other controls you have on the dialog -->
        <Button Content="Accept"/>
    </Grid>
</UserControl>

非常简单,只需将所有内容移动到用户控件即可。然后,只需包含此控件,窗口本身就会变得微不足道:

<Window .......>
    <controls:MyDialogContent ..../>
</Window>

到目前为止,没有任何变化,您发布的方法与以前完全相同。我们将把它保留为仅 WPF,然后为 WinForms 实现一个几乎相等的方法。

在 WinForms 项目中,现在您必须创建将取代 MyDialog 的表单。此表单可以像 WPF 版本一样简单,只是一个 ElementHost,它将包含您之前分离的 UserControl,可能还有您的逻辑所需的任何属性/方法。

最后一部分是提供一个 WinForms 方法来调用它,类似于 WPF 的方法。这可以像这样简单:

private static void ExecuteInternal(Form owner,
                                    string windowTitle,
                                    string label,
                                    object operation,
                                    MyDialogSettings settings)
{
    MyDialogForm dialog = new MyDialogForm(windowTitle, settings);
    dialog.Owner = owner;
    dialog.Label = label;

    dialog.ShowDialog();
}

【讨论】:

  • 我认为你没有得到我真正的问题...从表单打开 WPF 窗口不是问题。因此,您不需要将这些东西包装在 UserControl 中。在您的最后一个ExecuteInternal 版本中,您向界面发布了一个表单,因此使用该库的每个人都必须引用表单命名空间(甚至只有 WPF 用户)。这就是我想要避免的
  • ExecuteInternal 的版本(以及您自己的版本)并不意味着可重用,正如您所指出的,它与 WPF/WinForms 相关联。唯一可以作为公共库的一部分导出的是UserControl 本身,而不是Window,而不是ExecuteInternal 部分。这些都与各自的技术相关,但用户控件在两种环境中都是可互操作的。仅考虑 ExecuteInternal 一个辅助方法,这是唯一必须作为样板复制粘贴到其他项目中的部分,因此您最终会得到其中两个,仅是 private 方法。
猜你喜欢
  • 2017-02-15
  • 2020-03-09
  • 2015-09-19
  • 1970-01-01
  • 2016-12-08
  • 1970-01-01
  • 1970-01-01
  • 2018-08-09
  • 1970-01-01
相关资源
最近更新 更多