【问题标题】:Passing Data from WinForm to WPF将数据从 WinForm 传递到 WPF
【发布时间】:2013-11-28 05:09:57
【问题描述】:

我希望将数据从 WinForm 传递到 WPF 窗口并从 WPF 窗口接收回消息。

我的代码是随机在线教程和 HighCore 的 log viewer 的混合体。我有一个 WinForm 以下列方式启动我的新 WPF 窗口:

private void openTransactionViewToolStripMenuItem_Click(object sender, EventArgs e)
  {
     var transactionViewWindow = new TransactionViewer.MainWindow();
     ElementHost.EnableModelessKeyboardInterop(transactionViewWindow);
     transactionViewWindow.Show();
     transactionViewWindow.Test = "test";   // testing out data passing
     transactionViewWindow.AddTest();
  }

我的 MainWindow.xaml.cs 看起来像:

public partial class MainWindow : Window
{
  public ObservableCollection<Session> SessionList { get; set; }
  public string Test{ get; set; }

  public MainWindow()
  {
     InitializeComponent();

     SessionList = new ObservableCollection<Session>();

     SessionList.Add(new Session() { BeginLine = 0, EndLine = 1, Message = "some message" });
     SessionList.Add(new Session() { BeginLine = 2, EndLine = 3, Message = "another message" });

     SessionItems.ItemsSource = SessionList;  // the ItemsControl
  }

  public void AddTest()
  {
     SessionList.Add(new Session() { BeginLine = 4, EndLine = 5, Message = Test });
  }
}

public class Session : PropertyChangedBase
{
   public int BeginLine { get; set; }
   public int EndLine { get; set; }
   public string Message { get; set; }
}

其中PropertyChangedBase 继承自INotifyPropertyChanged。我有一个绑定到Message 的 ItemsControl。我的输出看起来像:

一些消息
另一条消息
测试

“数据传递”成功!最终,当 WPF 窗口加载时,我想从我的 WinForm 传递一个List&lt;Session&gt;,它将用于填充 ItemsControl。我还希望在 WinForm 上有一个按钮,它将发送一个列表来重新填充/刷新 WPF 中的数据。从当前的行为来看,我认为即使使用我当前的简单实现(只需更新SessionList),这也是可能的。

有没有更合适的方法来做到这一点?例如事件?我是否需要触发一个事件以告诉我的 WinForm WPF 已成功添加所有 Session 对象,或者每当用户单击特定对象时?
在这里使用 MVVM 有什么好处?

我已经为 WinForms 开发了一段时间,发现向 WPF 的过渡非常混乱。希望有人可以提供一些指导或代码示例。

编辑:供将来参考,可以在此处找到针对像我这样的人的体面的 MVVM 教程:http://jpreecedev.com/2013/06/08/wpf-mvvm-for-winforms-devs-part-1-of-5/

【问题讨论】:

  • 那么你在同一个进程中有 WPF 和 WinForms 吗?同一个程序集?
  • @JeffBridgman 是的,他们也在同一个解决方案中。我在现有解决方案中添加了一个 WPF 自定义控件库项目。

标签: c# .net wpf winforms xaml


【解决方案1】:

我觉得你的方法没问题。它并不完美,但足够实用。

IMO 的最佳方法是为 WPF 窗口创建一个 ViewModel,而不是在来回传递数据时直接引用 Window 本身。

想法是:

public class MyForm: Form
{
   public TransactionViewerViewModel TransactionViewer {get;set;}

   //... other code...

   //Form constructor:
   public MyForm()
   {
       InitializeComponent();

      //Create ViewModel:
      TransactionViewer = new TransactionViewerViewModel();
   }

   private void openTransactionViewToolStripMenuItem_Click(object sender, EventArgs e)
   {
      //Create WPF View:
      var transactionViewWindow = new TransactionViewer.MainWindow();

      //Interop code
      ElementHost.EnableModelessKeyboardInterop(transactionViewWindow);

      //Set DataContext:
      transactionViewWindow.DataContext = TransactionViewer;     

      //Show Window:
      transactionViewWindow.Show();

      //Call methods on the ViewModel, rather than the View:
      TransactionViewer.Test = "test";   // testing out data passing
      TransactionViewer.AddTest();
   }
}

所以,ViewModel 应该是这样的:

public class TransactionViewerViewModel : PropertyChangedBase
{
  public ObservableCollection<Session> SessionList { get; set; }
  public string Test{ get; set; }

  public TransactionViewerViewModel()
  {
     SessionList = new ObservableCollection<Session>();

     SessionList.Add(new Session() { BeginLine = 0, EndLine = 1, Message = "some message" });
     SessionList.Add(new Session() { BeginLine = 2, EndLine = 3, Message = "another message" });

  }

  public void AddTest()
  {
     SessionList.Add(new Session() { BeginLine = 4, EndLine = 5, Message = Test });
  }
}

这实现了 WPF UI 和实际数据/业务逻辑之间的完美分离,以至于您甚至可以为您的 ViewModel 创建单元测试。

而且,由于您将 ViewModel 设置为 Window 的 DataContext,因此您需要通过 DataBinding 访问您的所有 ViewModel 属性,而不是程序代码:

<ItemsControl ItemsSource="{Binding SessionList}"/>

那么,你可能想在ViewModel中引入delegatesevents,并在你的Form中监听这些,从而实现WPF =&gt; winforms通信。

【讨论】:

  • HighCore 来救援!谢谢,这正是我需要的。 (我基本上从你那里学到了 WPF:P)
  • 后续...here 描述的解决方案是否可以与 MVVM 一起用于 WPF -> WinForm 通信?
  • @valsidalv 是的,它使用部分 Prism 框架(这是微软的官方 MVVM 框架),以分离的方式在 WPF 和 winforms 之间发送“消息”。这是最好的解决方案,IMO,尽管它在架构和结构设计方面增加了一些开销。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多