4

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

我的代码混合了随机在线教程和 HighCore 的日志查看器。我有一个 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。我有一个 ItemsControl 绑定到Message. 我的输出看起来像:

一些消息
另一个消息
测试

“数据传递”成功!最终,当 WPF 窗口加载时,我想List<Session>从我的 WinForm 中传递一个用于填充 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/

4

1 回答 1

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 => winforms交流。

于 2013-11-15T02:09:17.307 回答