这是我在StackOverflow中的第一个问题。由于缺乏声誉,我无法发布任何链接或图像。 我已经处理了以下问题超过2天了。非常感谢任何帮助。
在我提出问题之前,这就是我所拥有的以及我所期待的:
由于以下原因,上述情况无法避免:
预期功能:
我有一个
WPF控件(例如,文本框)
我在上面提到的DateTime Winforms UserControl。
“取消”按钮基本上会重置上述控件。
当我点击取消按钮时,我将ViewModel
中的事件发布为 RunViewModel 到 WPF UserControl 代码后面的文件,说 RunView.xaml.cs。
eventAggregator.GetEvent<ResetDateTimeEvent>().Publish(true);
在代码隐藏文件中,我已按照以下方式订阅了该活动
eventAggregator.GetEvent<ResetDateTimeEvent>().Subscribe(ResetDateTimeHandler);
WPF 控件重置为默认值,但 DateTime UserControl 未重置。
因此,出于测试目的,我删除了ElementHost控件,并使用一个承载DateTime Winforms UserControl的WindowsFormsHost控件和一个WPF&#34;取消&#34;按钮。
当我点击按钮时,DateTime控件的值重置为其默认值。
然后,我认为这可能是我的DateTime Winforms UserControl的一个问题。 所以,我在实际应用程序中使用 Winforms 文本框控件替换我的DateTime Winforms UserControl。所以现在嵌套如下:
WinForms-ElementHost-WPF-WindowsFormsHost-Winforms Textbox
这是xaml代码。
<WindowsFormsHost x:Name="ReportFromDtTmHost" Margin="8,0" Grid.Column="0"
LostFocus="ReportFromDtTmHost_LostFocus">
<WindowsFormsHost.Child>
<winforms:TextBox x:Name="ReportFromDateTime"/>
</WindowsFormsHost.Child>
</WindowsFormsHost>
在初始加载时,我正在使用Textbox
文本
Initial Load Text
private void Window_Loaded(object sender, EventArgs e)
{
ReportFromDateTime.Text = "Initial Load Text";
}
正如我上面提到的,当我点击取消按钮时,会发生以下情况:
从ViewModel发布事件
eventAggregator.GetEvent()出版(真);
订阅代码隐藏文件(xaml.cs)中的事件:
eventAggregator.GetEvent()订阅(ResetDateTimeHandler);
已发布活动的EventHandler。
private void ResetDateTimeHandler(bool cancelClicked) { ReportFromDateTime.Text =&#34;重置为默认值&#34 ;; }
正如您在上面的代码中所看到的,我在单击“取消”按钮时重置了文本。
在调试过程中,我可以看到Text属性被更改为&#34;重置为默认&#34;,但UI不会显示这些更改。
这是一个奇怪的部分:
WindowsFormsHost控件上的 Child 属性与实际的“ReportFromDateTime”Textbox控件不同。
在调试时,我可以看到WindowsFormsHost控件上的Child和Name属性不同。 Name属性为空,
ReportFromDtTmHost.Child.Name = ""
应该是 ReportFromDateTime 。
似乎主机和子控件正在重新创建。
据我所知,我认为嵌套(WinForms-ElementHost-WPF-WindowsFormsHost-Winforms Textbox)的额外级别可能会导致WPF和Winforms之间的互操作问题。
我已经做了很多研究并搜索了很多建议链接。我发现没有人指出这个问题。其中一些人很亲密。以下是几个链接:
this suggests重现“代理Windows格式消息循环”部分下的消息循环。
Here is one more link解释了嵌套部分下嵌套的问题。
我为道歉而道歉。只是想让你们清楚地了解我的问题。如果您对该帖子有任何疑问,请与我们联系。任何建议都将不胜感激。修改:
我们能够解决问题,但仍然是一种解决方法。这是我们做的: 有两种方法可以解决此问题,但两者都与使用静态相关。
静态Winforms控件:
我们使用了以下静态Winforms控件
public static class ControlHolder
{
public static TextBox ReportFromDateTimeInstance;
}
在&#34;实际&#34;的 OnChanged 事件中控制,我们将实际控件,ReportFromDateTime转储到静态控件,ReportFromDateTimeInstance。
private void ReportFromDateTime_TextChanged(object sender, EventArgs e)
{
ControlHolder.ReportFromDateTimeInstance = (TextBox)sender;
}
从那时起,无论我们更新实际控件(如 ResetDateTimeHandler
方法),我们更新静态控件
private void ResetDateTimeHandler(bool cancelClicked)
{
ControlHolder.ReportFromDateTimeInstance = "Text changed";
}
显示前端的更新值
静态EventAggregator
这项解决方案由我们的一位同事提供。
在这种情况下,我们使用的是实际控件 ReportFromDateTime ,而不是静态控件ControlHolder.ReportFromDateTimeInstance
我们使用静态事件聚合器来发布/订阅ResetDateTimeEvent,而不是使用Unity Container提供的Event Aggregator实例。所以,而不是
eventAggregator.GetEvent<ResetDateTimeEvent>.Publish(true);
我们用过:
ResetDateTimeEvent.Instance.Publish(true);
在订阅中:
ResetDateTimeEvent.Instance.Subscribe(ResetDateTimeHandler);
我知道在这种情况下我们不需要使用静态事件聚合器,因为我们使用的是Unity Container提供的实例(这可以确保所有ViewModel共享一个实例),但这也解决了这个问题
因此,我仍然对上述两种情况解决问题的原因感到困惑。是静态 - 正在解决问题吗?
正如我已经说过的那样,我觉得控件正在重新创建,当我们掌握控件时,它们已经被重新创建了。
非常感谢任何建议。
答案 0 :(得分:0)
我之前在一个在WinForms控件中有WPF控件的应用程序中做过同样的事情。 WPF使用Prism / Unity(后来切换到MEF)来启动所有操作。但是,这默认在引导程序中创建了一个全新的EventAggregator,所以我在容器中覆盖了默认的IEventAggregator,并且已经创建了WinForm端并使用自己的IEventAggregator实例。症状类似,未发布已发布的事件。
在像你这样的混合系统中,单例非常适合确保所有内容都以相同的引用为基础,特别是当您的启动处于分阶段时(WinForms然后是WPF)。
简单回答:是的,使用单例作为WinForms代码和WPF代码之间的共享引用。这些单例可以在WPF引导程序中输入容器,这样也可以在WPF端进行注入。