2013-06-07 18 views
6

Pracuję nad moim pierwszym projektem w MVVM i zdecydowałem się użyć MVVM Light Toolkit. Mam , który obsługuje firmę na głównym ekranie mojej gry. Potrzebuję dowiedzieć się, jak otworzyć nowe okno (AdventurerView) z instancją Adventurer jako parametrem podczas wykonywania polecenia, czy jest ono powiązane z AdventurerViewModel oraz wyświetlać i zwracać dane. Instancje tego okna będą często otwierane i zamykane. Utknąłem na tym od kilku dni i to doprowadza mnie do szału. Chciałbym nauczyć się, jak to zrobić w sposób przyjazny dla MVVM, najlepiej za pomocą narzędzi dostarczonych przez MVVM Light lub czysty XAML.MVVM Light & WPF - Wiązanie Wiele instancji okna do ViewModel

Próbowałem używać MVVM Light's ViewModelLocator, ale ponieważ AdventurerView jest oknem, to nie zadziała; jest napisane "Nie można umieścić okna w stylu", ale program nadal się kompiluje i działa. Czy może być coś, co mógłbym zmienić, aby to zadziałało? Czy istnieje inny sposób wiązania ich w XAML? Lub całkowicie inne podejście? Naprawdę chciałbym móc od tego odejść. Próbowałem również używać komunikatora MVVM Light bez rezultatu (który nadal nie rozwiązuje problemu View/ViewModel).

Po prostu muszę mieć możliwość utworzenia okna, które jest powiązane z AdventurerViewModel i wyświetla/zwraca odpowiednie dane.

AdventurerView.xaml znajduje się obecnie w stanie domyślnym, ale uważam, że mógłbym powiązać odpowiednie dane, które mogą pomóc (DataContext).

AdventurerViewModel jest całkiem goły jak dobrze

class AdventurerViewModel : ViewModelBase 
{ 
    #region Members 

    private Adventurer _adv; 

    #endregion 

    #region Properties 

    public Adventurer Adv 
    { 
     get { return _adv; } 
     set { _adv = value; } 
    } 

    #endregion 

    #region Construction 

    public AdventurerViewModel(Adventurer adv) 
    { 
     this._adv = adv; 
    } 

    #endregion 
} 

App.xaml z nieprodukcyjnym DataTemplate na dole:

<Application StartupUri="MainWindow.xaml" 
     xmlns:views="clr-namespace:AoW.Views" 
     xmlns:vm="clr-namespace:AoW.ViewModels" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     x:Class="AoW.App" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d"> 

<Application.Resources> 
    <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" /> 

    <DataTemplate DataType="{x:Type vm:GameViewModel}"> 
     <views:GameView /> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type vm:TitleViewModel}"> 
     <views:TitleView /> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type vm:AdventurerViewModel}"> 
     <views:AdventurerView /> 
    </DataTemplate> 

</Application.Resources> 
</Application> 

Komenda w które miejmy nadzieję uczynić to wszystko wydarzy (komunikat tylko potwierdza, że ​​polecenie jest uruchamiane):

private void ExecuteShowAdvCommand(Adventurer adv) 
    { 
     System.Windows.MessageBox.Show(adv.Name); 
    } 

Naprawdę nie wiem, co jeszcze dodać.

+1

Czy użyłeś 'Messenger', który pochodzi z mvvm-light? Mówiąc prościej, po pierwsze NIE zadeklaruj nowego okna jako 'DataTemplate' w twoim xaml MainWindow. To, co robisz jest w 'GameViewModel', kiedy potrzebujesz stworzyć swój" AdventureView ", wyślij wiadomość do' MainWindow', która powinna zarejestrować i odebrać ten komunikat w kodzie z tyłu, utwórz 'AdventureView' i wywołaj' Show() ' lub 'ShowDialog()' odpowiednio. 'SimpleIoC' powinien obsługiwać tworzenie VM dla' AdventureViewModel'. Czy to ma dla ciebie sens? – Viv

+1

http://stackoverflow.com/questions/3386349/how-to-open-a-new-window-using-mvvm-light-toolkit pokazuje przykład otwarcia nowego okna przy użyciu MVVM Light. Jest kilka innych opcji robienia tego samego, ale powinien to być dobry początek. Teraz, wysyłając te "wiadomości", możesz przekazać dowolnie wybrany argument, upraszczając przekazywanie informacji o parametrach: – Viv

+1

, tak jak w przypadku otrzymania odpowiedzi, która zależy od sposobu odzyskania danych, jeśli jest to dialog, który możesz wywołać ShowDialog, który będzie modalny i sprawdź jego wartość zwracaną lub ponownie użyj 'Messenger', aby wysłać wyniki z powrotem do" GameViewModel' – Viv

Odpowiedz

22

Ok ułożyła demo, które powinny uczynić to mam nadzieję, że łatwiej można Download Link

Funkcjonalność:

  • 3 Okna w sumie (MainWindow, ModalWindow, NonModalWindow)
  • MainWindow ma TextBox możesz wpisać cokolwiek chcesz.
  • 2 przyciski na górze otworzy Modal/NonModal Okno odpowiednio
  • Każde okno po otwarciu pojawi się komunikat, który był w MainWindow na TextBox w TextBlock wewnątrz nich.
  • W każdym oknie można zaznaczyć CheckBox, aby zaktualizować wartość w bloku tekstowym wyników w MainWindow (dla okna modalnego zostanie ono uruchomione, gdy okno modalne zostanie zamknięte.Dla NonModal zmiany mogą być postrzegane ASAP)

to jest to za funkcjonalność,

Pojęcia:

  • Rejestrowanie wielokrotne VM z SimpleIoC i korzystania GetInstance(...) zwrócić je.
  • Messenger klasy użytkowania z niestandardowego typu wiadomości OpenWindowMessage
  • Otwarcie Modal/Non Modal Windows z rodzicem VM pozostaje wierna zasadom MVVM
  • danych przepływających między oknami (tylko pokazanych w NonModal)

Ważna uwaga: - metoda stosowana w tym przykładzie ustawienie non DP DialogResult z modalnego okna nie jest przyjazne dla MVVM cos używa kodu źródłowego ustawić właściwość DialogResult na WHI Window.Closing zdarzeń ch należy unikać (jeśli chcesz być "testowalny"). Moje preferowane podejście jest trochę długie i jest bardzo dobrze udokumentowane HERE (Mieszanina pytań i odpowiedzi). Dlatego też zignorowałem to ze względu na tę próbkę.

+1

Dziękuję za tak niewiarygodną odpowiedź. Myślę, że prawie teraz działam. Podczas próby otwarcia nowego okna pojawia się błąd - "XamlParseExcption" wystąpił, wskazując linię w oknie modalnym dotyczącym DataContext i nie mam pojęcia, dlaczego to robi. –

+0

Teraz nie mam pojęcia, jak te linie się tam dostały. Usunąłem to i teraz nie otrzymuję żadnych błędów, ale okno się nie wyświetla. –

+0

Wszystko, co musiałem zrobić, to zadzwonić .Show() - Teraz działa. Szkoda, że ​​mogę tylko raz odpowiedzieć na tę odpowiedź. I ostatnia rzecz: jeśli otworzę drugie okno, zmieni ono informacje z pierwszego na drugie. Czy istnieje sposób, aby temu zapobiec? Jeszcze raz dziękuję za tak wspaniałą odpowiedź! –

1

Po wykonaniu Viv, zmodyfikowałem próbkę tak, aby zawierała przykład otwarcia okna bez użycia kodu.

Sample project is here.

ja wykorzystując singleton ViewModelLocator ze statycznej metody tej wiadomości aż viewmodel i okna oraz kontekstu danych zamiast kodu tył.

Blog Post with Details. Poinformuj mnie, która metoda jest preferowana. Nie podoba mi się używanie kodu z tyłu, ale może być brakujący i cona.

+4

Po pierwsze "nielubienie" zza kodu (bez konkretnej przyczyny) jest bardzo słabym argumentem. Możesz znaleźć niezliczone przykłady ludzi mówiących: "nie wszystko z tyłu jest błędne w MVVM", więc nie będę tutaj ponownie rozpoczynać tego tematu. Zignorowanie tego trochę, To podejście prawie nie oferuje "dodatkowej korzyści" i wprowadza bez żadnego ładunku cały ładunek. Jeśli więc muszę opracować i uzasadnić to twierdzenie, po pierwsze, proces tworzenia nowego okna i pokazywania go nie jest "testowany jednostkowo". – Viv

+1

..cont'd. Po drugie, masz teraz silną zależność od 'ViewModelLocator' w' MainViewModel' (aby wywołać funkcję statyczną). Zatem testy jednostkowe dla MainViewModel muszą teraz zapewniać tę klasę, ale nie mogą zapewnić tego samego, co kod live cos, który wymaga tworzenia elementów interfejsu użytkownika. W związku z tym trzeba udawać "ViewModelLocator" i prawdopodobnie uczynić go usługą interfejsu, aby przekazać inną instancję dla testów jednostkowych i jedną dla kodu na żywo – Viv

+2

..cont'd. z drugiej strony otrzymałeś wiadomość, że możesz zapisać się do testów Unit i skończysz z nią. Zatem cała ta zmiana przeniesienia kodu z kodu z tyłu do 'ViewModelLocator' służy temu, że" Moja klasa z kodem jest pusta ", kiedy nie musi być na pierwszym miejscu i myślenie, że powinno być złe jest na początku. .Również "ViewModelLocator", jak sama nazwa wskazuje, jest pomocnikiem IoC. wykonanie okna otwierania/zamykania jest początkowo dość dziwne. Wolałbym wiedzieć, które łańcuchy okien, z których wywodzą się inne, i moje zależności wywodzą się z tego. – Viv

Powiązane problemy