Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# NET Core 3.1 WinForms Designer与WPF用户控件不兼容_C#_Wpf_Winforms_.net Core - Fatal编程技术网

C# NET Core 3.1 WinForms Designer与WPF用户控件不兼容

C# NET Core 3.1 WinForms Designer与WPF用户控件不兼容,c#,wpf,winforms,.net-core,C#,Wpf,Winforms,.net Core,一年多前,我开始使用Windows窗体编写.NET Framework 4.6.1应用程序。当时我知道WPF,但熟悉Windows窗体,它拥有我所需要的大部分控件。对于缺少的控件,我在Windows窗体中编写了两个,在WPF中编写了一个。所有这些都很好地共存,WPF控件在一个元素宿主中进行了容器化 本周,我开始迁移到.NETCore3.1。我对项目副本的测试是肯定的,实际迁移的初始结果也是肯定的。经过小规模的重构,解决方案构建并运行时没有问题。然后,在WinForms Designer中打开主U

一年多前,我开始使用Windows窗体编写.NET Framework 4.6.1应用程序。当时我知道WPF,但熟悉Windows窗体,它拥有我所需要的大部分控件。对于缺少的控件,我在Windows窗体中编写了两个,在WPF中编写了一个。所有这些都很好地共存,WPF控件在一个元素宿主中进行了容器化

本周,我开始迁移到.NETCore3.1。我对项目副本的测试是肯定的,实际迁移的初始结果也是肯定的。经过小规模的重构,解决方案构建并运行时没有问题。然后,在WinForms Designer中打开主UI表单后,小精灵出现了。回到.NETFramework,我的所有自定义控件都出现在设计器的工具箱中,可以方便地拖放到窗体上。在.NETCore中,工具箱中只显示WinForms控件,而不显示WPF控件。因为设计器看不到该控件,所以将其从窗体的设计器代码中剥离,留下一个空的元素宿主

这是踢球的人。恢复设计器的更改后,接受对窗体设计器代码的任何直接手动编辑,生成项目成功并运行良好。因此,出于某种原因,设计者不喜欢WinForms中的WPF控件

我尝试过的事情:

  • 在测试过程中,我发现WinForms主UI需要将“UseWindowsForms”和“UseWPF”设置为“true”才能编译项目。然后,我将“UseWindowsForms”参数添加到WPF用户控件库中。这导致该控件出现在设计器的工具箱中,但尝试添加该控件导致此错误:“未能创建组件。。。Microsoft.DotNet.DesignTools.Client.DesignTools服务器异常。。。确保该类型实现IComponent并提供适当的公共构造函数。适当的构造函数要么不接受任何参数,要么只接受一个IContainer参数。“代码中现有的WPF控件仍然被删除
  • 我将WPF控件从库复制到主UI项目,编辑了名称空间,并删除了库项目引用。结果与上面相同
  • 创建了一个新的Windows窗体用户控件库,将“UseWPF”添加到项目中,并将WPF控件复制到此库。结果与上面相同
  • 回到我的项目的测试副本,我遵循了微软的“尝试转换”和“升级助手”指南。后者起初似乎很有希望,因为它替换、修改或删除了过时的引用和软件包。但没有成功
  • 使用.NET Core 3.1和.NET 5尝试了上述迁移步骤。结果相同
我现在的重点是继续手动编辑表单的设计器代码。这不适合进行大的更改,而且如果将此项目传递给其他开发人员,也不可持续。有什么想法吗?我应该尝试将Windows窗体UI移植到WPF吗?或者这仅仅是相对较新的.NET核心Windows窗体Des的成熟度问题吗igner

Visual Studio版本:Community 2019 16.9.3

IComponent错误的屏幕截图:

我终于想出了一个解决办法;这个想法是由ElementHost控件的Microsoft文档页面引发的:

本质上,将WPF控件宿主从主UI移动到WinForms控件库中。因此,此WinForms控件库中的用户控件将是WPF控件的包装器。以下是我在测试VS解决方案中采取的步骤:

  • 从我在测试期间添加的主UI项目文件中删除“true”条目
  • 在新的WinForms控件库中,将“true”添加到“true”项下的项目文件中。这使该库成为两个UI框架之间的桥梁
  • 如果主机的WPF控件位于专用控件库中(如我的),则将此项目作为依赖项添加到WinForms控件库中
  • 在WinForms库中创建新的用户控件(如果还没有)
  • 在设计器中,使用“填充”停靠将面板容器添加到控件中。我将面板命名为“panelWpf”
  • 这就是Microsoft文档的作用。在WinForms控件的代码隐藏文件中,我首先添加了ElementHost控件和WPF控件作为私有全局变量。然后,在WinForms“Load”事件中,我设置了ElementHost停靠样式,将WPF添加为子控件,最后将ElementHost作为控件添加到“panelWpf”中“集装箱。下面是这个文件中的代码。“WpfControlLibrary31”是我的WPF控件库项目,“TestControl31”是WPF控件本身。最后,“WpfTest”是包装器WinForms用户控件的名称
  • 在构建WinForms控件库之后,它出现在主UI项目的工具箱中,我可以像其他Windows窗体控件一样将其添加到窗体中。接下来的步骤是将事件处理程序、getter、setter等添加到控件中,以进行所需的交互
  • 思想

  • 有些人可能想知道我为什么使用面板容器。在这个简单的实验中,它是过度杀戮;我可以简单地将ElementHost对接到控件本身。但是,如果WinForms用户控件具有更复杂的设计,则面板将成为占位符,同时仍允许使用设计器。此外,如果WPF控件周围需要边框或类似的设计,那么面板也可以这样做
  • 将ElementHost和WPF控件对象作为全局对象允许从所有控件的方法进行访问,显然,就像设计器中添加的任何控件一样
  • 主机的WPF控件不需要位于专用的WPF控件库项目中。如果它是预先存在的WPF控件(例如MediaElement),则将其用于全局WPF对象
  • 这个WinForms控件库正是我一直以来巩固和提高自定义c语言效率所需要的
    using System;
    using System.Windows.Forms;
    using System.Windows.Forms.Integration;
    
    
    namespace WinFormsLibrary
    {
        public partial class WpfTest : UserControl
        {
            // ElementHost for the WPF control
            private ElementHost host = new ElementHost();
            // WPF control to be hosted
            private WpfControlLibrary31.TestControl31 uc = new WpfControlLibrary31.TestControl31();
    
            public WpfTest()
            {
                InitializeComponent();
            }
    
            private void WpfTest_Load(object sender, EventArgs e)
            {
                // set the docking style for the ElementHost
                host.Dock = DockStyle.Fill;
    
                // add the WPF control as a child of ElementHost
                host.Child = uc;
    
                // add the ElementHost as a control of the panel container
                panelWpf.Controls.Add(host);
            }
        }
    }