2013-11-14 3 views
4

Я ищу, чтобы передать данные в окно WPF из WinForm и получить сообщение из окна WPF.Передача данных из WinForm в WPF

Мой код представляет собой сочетание случайных онлайн-обучающих программ и HighCore's 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. У меня есть элемент ItemsControl, связанный с Message. Мой вывод выглядит:

некоторые сообщения
другое сообщение
тест

"Передача данных" является успешным! В конце концов, когда загружается окно WPF, я хочу передать List<Session> из моего WinForm, который будет использоваться для заполнения ItemsControl. Я также хочу иметь кнопку на WinForm, которая отправит список для повторного заполнения/обновления данных в WPF. Из текущего поведения я думаю, что это будет возможно даже с моей текущей, простой реализацией (просто обновление SessionList).

Есть ли более подходящий способ сделать это? Например, события? Нужно ли мне запускать событие, чтобы сообщить моему WinForm, что WPF успешно добавил все объекты Session или каждый раз, когда пользователь нажимает на конкретный?
Любая польза от использования MVVM здесь?

Я разрабатывал для WinForms какое-то время, и переход на WPF довольно запутан. Надеюсь, кто-то может помочь с некоторыми инструкциями или примерами кода.

Edit: для будущей ссылки, достойный MVVM учебник нацелен на людей, как я, можно найти здесь: http://jpreecedev.com/2013/06/08/wpf-mvvm-for-winforms-devs-part-1-of-5/

+0

Итак, у вас есть WPF и WinForms в том же процессе? Такая же сборка? –

+0

@JeffBridgman да, они тоже в одном решении. Я добавил проект библиотеки пользовательского контроля WPF для моего существующего решения. – valsidalv

ответ

1

Вы подход кажется хорошо для меня. Это не идеально, но это достаточно эффективно.

Оптимальным подходом, IMO, было бы создание ViewModel для окна WPF вместо прямого ссылки на сам 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 и фактических данных/бизнес-логики, к что вы даже можете создать Unit Tests для своей ViewModel.

И, так как вы устанавливаете ViewModel как окна DataContext, вам нужно будет обратиться ко всем свойствам ваш ViewModel через DataBinding, а не процедурный код:

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

Затем вы можете ввести delegates или events в ViewModel, и прослушайте их в своей форме, таким образом получив сообщение WPF => winforms.

+1

HighCore на помощь! Спасибо, это именно то, что мне нужно. (Я в основном узнал от вас WPF: P) – valsidalv

+0

Следующее ... это решение, описанное здесь [http://blogmarq.co.uk/index.php/launch-wpf-window-from-winforms- host /), приемлемый для использования с MVVM для обмена WPF -> WinForm? – valsidalv

+0

@valsidalv yes, он использует части платформы Prism (которая является официальной MVVM Framework от Microsoft), для отправки «сообщений» между WPF и winforms развязанным способом. Это лучшее решение, IMO, хотя оно добавляет некоторые накладные расходы с точки зрения архитектуры и структурного проектирования. –

Смежные вопросы