2011-02-06 11 views
9

Jestem nowy w firmie MVVM i zdecydowałem się przejść do niej i zacząć ją stosować w moich nadchodzących projektach.Przełączanie między trybem wyświetlania i trybem edycji w MVVM?

Przeczytałem to powiązane pytanie i odpowiedź, ale nie wiem, w jaki sposób zostałby on wdrożony w MVVM.

Chcę, aby wszystkie widoki w moim projekcie miały 2 tryby, tryb edycji i tryb widoku.
Nie chcę, aby użytkownik domyślnie widział pola TextBox dla wszystkich pól, wolałbym, aby widziały TextBlocks (lub ustawiają właściwość s 'jako IsReadOnly na true (poprzez styl itp., Powiedz mi ..)

Gdy użytkownik otwiera encję, zwykle powinny to być TextBlocks, Labels (lub readonly TextBoxes) itd., A jeśli kliknie "Edit" (jeśli ma uprawnienia), powinien przejść do trybu edycji, a wszystkie etykiety pól powinny zostać odwrócone do pól TextBox (RichTextBoxes itp., ComboBoxes lub innych edytowalnych pól, które nie są tylko etykietami).

Jestem pewien, że nie jestem jedynym, który ma ten problem, chciałbym usłyszeć od ekspertów, jaki jest najskuteczniejszy sposób przełączania b pomiędzy tymi trybami w czystej MVVM i czy powszechne jest zadeklarowanie dla niego dwóch osobnych widoków.

Proszę odnieść się do dobrego artykułu, który wyjaśnia, jak to zrobić (może to zrobić Visual Law? IDK).

UPDATE
Chcę wiedzieć, co zamiast JAK, moje pytanie jest o strukturze i jest powinienem oddzielić tryb edycji od trybie podglądu na obu V lub VM? Proszę podkreślić ten szczegół w swojej odpowiedzi.

Z góry dziękuję.

Odpowiedz

10

Użyj właściwości IsReadOnly dla pól tekstowych, a wiążą się, że do „trybu edycji” własności:

<TextBox .... IsReadOnly={Binding IsViewMode} ... /> 

Następnie w widoku modelu

public bool IsViewMode 
{ 
    get { return _IsViewMode; } 
    set 
    { 
     _IsViewMode= value; 
     // Call NotifyPropertyChanged when the source property is updated. 
     NotifyPropertyChanged("IsViewMode"); 
    } 
} 

IsViewMode domyślne do true i jest włączony do false, gdy użytkownik kliknie "edytuj". Wiązanie natychmiast zmieni wszystkie pola tekstowe.

Można zrobić to samo dla innych elementów sterujących - chociaż będzie to właściwość IsEnabled, do której musisz się przydać w tych przypadkach - mimo że masz wyszarzone elementy sterujące.

Aby zamienić na bloki tekstu i swoje kontrole trzeba mieć zarówno kontrole dzielące tę samą lokalizację w siatce i ich widoczność kontrolowane przez właściwość IsViewMode za pośrednictwem pary konwerterów:

<TextBlock Grid.Row="1" Grid.Column="2" ... 
      Visiblity={Binding IsViewMode, Converter=DirectConverter} ... /> 
<ComboBox Grid.Row="1" Grid.Column="2" ... 
      Visiblity={Binding IsViewMode, Converter=InvertedConverter} ... /> 

Bezpośrednim konwerter jest:

return IsViewMode ? Visibility.Visible : Visibility.Collapsed; 

odwróconego konwerter jest:

return IsViewMode ? Visibility.Collapsed : Visibility.Visible; 
+0

A co z innymi polami? Powiedziałem, że chcę, aby niektóre pola były odwrócone do DropDown, niektóre do suwaka, inne do selektora daty, podczas gdy w trybie wyświetlania wszystkie są proste TextBlocks/labels? To bardzo ważna część dla mnie. – Shimmy

+0

@Shimmy - przepraszam, tęskniłem za tym trochę (nie wiem dlaczego). Możesz zrobić to samo dla ComboBoxes, ale może to być właściwość 'IsEnabled', z którą musisz się połączyć. – ChrisF

+0

Więc zasadniczo mówisz, że powinienem zrobić wspólny widok dla trybów edycji/widoku, mając wszystkie kontrolki zadeklarowane jeden blisko innego ustawienia IsReadOnly lub Kontrola widoczności do IsViewMode na VM (używając konwertera BooleanToVisibility dla kontrolek do ukrycia), jest to prawda? ** Dodałem trochę treści do mojego pytania. ** – Shimmy

2

Viewmodel: Zdecydowanie zachowałbym tylko jeden model podglądu z właściwością ViewMode, podobnie jak to opisano w odpowiedzi ChrisF. Oddzielne ViewModels byłoby po prostu nieeleganckie.

Widok: Jak widzę, masz co najmniej trzy opcje, z różnymi zaletami i wadami.

  1. Tylko do odczytu wszystkich elementów sterujących, zgodnie z sugestią udzieloną przez Chrisa. Zalety: Najprostsza rzecz do zrobienia. Minusy: To jest brzydki interfejs w mojej skromnej opinii.

  2. Twórz seaparate display i edytuj kontrolki w oddzielnych kontenerach. Wiąż widoczność kontenerów z ViewMode. Zalety: Tutaj można uzyskać przyjemniejsze wrażenia z ui. Możesz nawet animować przejścia z jednego do drugiego. Wady: podwaja liczbę kontroli (może zaszkodzić wydajności w przypadku bardzo dużych okien). Pozycjonowanie elementów sterujących w dwóch pojemnikach dokładnie w tych samych pozycjach piksela może stać się nieco nietrywialne w płynnym ui.

  3. Dla każdej kontroli edycji w Xaml, umieść kontrolkę wyświetlania tuż nad nią. Określ widoczność właściwości ViewMode. Plusy: brak powielania kontroli etykiet przynajmniej, więc nieco szybciej. Wady: trudniejsze do uzyskania animacji i innych poprawek w widoku.

Edit: W świetle wyjaśnień udzielonych wybrałem zastąpić poprzednią odpowiedź, gdyż prawie w dużej mierze do czynienia z how, a nie co.

+0

Dodałem trochę treści do mojego pytania. Nie deklarowałbym tego w ten sposób. Nienawidzę tego, że ViewModel wie, że istnieje wyliczenie Widoczności ... Podążałbym za [ChrisF's answer] (http://stackoverflow.com/questions/4917047/switching-between-view-mode-and-edit-mode-in -mvvm/4917104 # 4917104) za pomocą konwerterów BooleanToVisibilit/BooleanFlagSwitch itp. Właśnie dostałem odpowiedź, że tryb widoku i tryb edycji NIE powinny być rozdzielane. – Shimmy

+0

@Shimmy: Myślę, że podczas gdy tryb wyświetlania i edycji powinien należeć do tej samej klasy widoku i związany z tym samym modelem wyświetlania, elementy sterujące dla nich powinny być oddzielone dla lepszego doświadczenia interfejsu użytkownika. Zmieniłem odpowiedź, by odzwierciedlać to samo. – anshul

+1

Nie ma absolutnie nic złego w modelu widoku, wiedząc, że istnieje coś takiego jak widoczność. –

3

Myślę o tym w następujący sposób: widok jest taki, jak wygląda, a ViewModel to sposób, w jaki wchodzi on w interakcję z użytkownikiem. Ponieważ interfejs tylko do odczytu ma zasadniczo inne zachowanie niż interfejs do odczytu/zapisu, powinny istnieć dwa różne modele ViewModels.

Teraz stworzyłem edytor ViewModel, który został odziedziczony po ViewModelu wyświetlacza, ponieważ uważałem, że funkcja edycji jest rozszerzeniem funkcjonalności wyświetlania. Działa to w prostych aplikacjach typu CRUD, w których użytkownik bezpośrednio edytuje pola bez dużej logiki biznesowej.

Z drugiej strony, jeśli masz bardziej skomplikowany proces biznesowy (lub przepływ pracy), który modelujesz, zazwyczaj sposób w jaki manipulujesz informacjami jest bardzo różny od sposobu, w jaki chcesz go wyświetlać. Dlatego generalnie oddzieliłbym dwa modele ViewModels, chyba że byłby to po prostu CRUD.

+0

Dokładnie, mówię o CRUD.Jak powiedziałem, że jestem nowy w MVVM i chcę się go nauczyć.Możesz polecić mi dobry artykuł o tym, jak zaimplementować aplikację CRUD w sposób MVVM? Moim problemem są również przejścia między różne opinie – Shimmy

+0

Dokładnie, mówię o CRUD.Jak powiedziałem, że jestem nowy w MVVM i chcę się go nauczyć.Możesz polecić mi dobry artykuł o tym, jak zaimplementować aplikację CRUD w sposób MVVM? ** Mój główny problemem są również przejścia między różnymi poglądami.** – Shimmy

+1

@Shimmy - Proponuję [Advanced MVVM] (http://joshsmithonwpf.wordpress.com/advanced-mvvm/) Josha Smitha. Jest krótki, ale bardzo pouczający i można uzyskać kod źródłowy. –

3

Odpowiedź ChrisF jest w porządku, jeśli chcesz iść na trasę IsReadOnly. Jeśli jednak chcesz przejść do TextBlock-to-TextBox, najbardziej efektywnym sposobem jest Control, który przełącza swój szablon za pomocą wyzwalaczy na podstawie wartości właściwości IsInEditMode lub IsInViewModel.

2

Po pierwsze, chciałbym wdrożyć abstrakcyjną klasę bazową dla modeli, które moim zdaniem realizowanych IEditableObject i narażonych odpowiednie polecenia dla BeginEdit, EndEdit i CancelEdit. Możliwe, że rzeczywiste implementacje tych trzech metod musiałyby należeć do klas pochodnych, ale komendy mogły żyć w klasie bazowej.

W tym podejściu EndEdit aktualizuje model z bieżącymi wartościami właściwości w modelu widoku.

Wprowadziłbym również booleanową właściwość IsEditing w klasie bazowej, do użycia w wyzwalaczach danych, więc jeśli chcę przełączać się między trybami bez (na przykład) otwierania modalnego okna dialogowego, mogę zrobić to w stylu .

Jeśli chodzi o wizualny projekt interfejsu front-end, uważam, że widok tylko do odczytu to tylko widok edycji z kontrolkami tylko do odczytu, który jest atrakcyjny przede wszystkim dla programistów. Mówiąc ogólnie, jeśli po prostu przedstawiasz obiekt użytkownikowi, celem tej prezentacji jest dostarczenie użytkownikowi czytelnej, przejrzystej i intuicyjnej reprezentacji informacji w tym obiekcie. Jeśli pozwalasz użytkownikowi edytować obiekt, celem tej prezentacji jest uczynienie zadania modyfikowania wszystkich edytowalnych właściwości obiektu tak łatwych i przejrzystych, jak to tylko możliwe.

Są to dwa bardzo różne zestawy celów. Na przykład, podczas gdy płeć, wzrost i waga osoby mogą być ważnymi informacjami dla aplikacji do zbierania, prawdopodobnie nie jest tak ważne, aby system przedstawiał te informacje użytkownikowi w większości kontekstów. Wydaje się to bardzo naturalne, jeśli masz w głowie to, że tryb edycji jest podobny do trybu wyświetlania. Ale jeśli umieszczasz potrzeby użytkownika, a nie programistę, z przodu i centrum, może to nie być właściwe.

Powiązane problemy