2013-03-02 1142 views
5

porządku, to jest w pewnym stopniu związane z tym pytanie: WPF Printing multiple pages from a single View ModelMVVM + UserControl + Zależność własności

starałem się przestrzegać zaleceń podanych tam, ale teraz jestem zablokowany.

Moja aplikacja korzysta z MainView.xaml i odpowiedniego MainViewViewModel.cs, używam MVVM Light w tle.

Teraz - zgodnie ze stanowiskiem - wydaje się, muszę wykonać następujące czynności:

  • Tworzenie formantu użytkownika
  • Expose pewne właściwości z kontrolą użytkownika
  • Upewnij model widok pokazuje te właściwości

Pomysł jest jasny, ale utknąłem, próbując się nawzajem powiadomić.

Moja kontrola użytkownika (UcTest.xaml) uwidacznia zależność obiekt:

public string SpecialText 
{ 
    get { return (string)GetValue(SpecialTextProperty); } 
    set 
    { 
     SetValue(SpecialTextProperty, value); 

    } 
} 

// Using a DependencyProperty as the backing store for SpecialText. This enables animation, styling, binding, etc... 
public static readonly DependencyProperty SpecialTextProperty = 
    DependencyProperty.Register("SpecialText", typeof(string), typeof(UcTest), new PropertyMetadata(new PropertyChangedCallback(SpecialTextChangedPropertyCallback))); 

private static void SpecialTextChangedPropertyCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
{ 
    // Do something 
    Debug.WriteLine("Ffgdgf"); 
} 

porządku, więc ja teraz mam kontrolę użytkownika, który ma pewne właściwości zależności. Jednak te właściwości są całkowicie oddzielone od moich właściwości ViewModel (są to te, które powinny być wyświetlane).

Więc w zasadzie mam dwie możliwości:

  • Jak mogę teraz powiedzieć mój ViewModel do UserControl, że niektóre właściwości uległy zmianie?
  • Czy istnieje możliwość zapomnienia o właściwościach zależności i bezpośredniego dostępu do modelu widoku?

Informacje dodatkowe # 1: mam uploaded (prosty) przykład tego, co staram się zrobić tutaj: Example Project. Chciałbym zmienić wartość etykiety w UserControl1 (poprzez właściwość binding w ViewModel dla UserControl1) z mojego MainViewViewModel.

+0

Użyj powiązania danych –

+1

To oznaczałoby, że mój UserControl musiałby zaimplementować INotifyPropertyChanged, co jest w zasadzie to, co powinien zrobić mój ViewModel. –

Odpowiedz

4

Dobra, po godzinach googlowanie wydaje się, że "poprawne" podejście do tego nie jest w ogóle wykonaniem. Ogólnym podejściem jest przechowywanie danych w MainViewModel i nie używanie dodatkowego ViewModel dla UserControl (który znajduję trochę ... no ... nie tak dobrze). Głównym problemem jest to, że nie ma łatwego mechanizmu, aby pobrać Dane z Własności Dependency do ViewModel.

Do druku wróciłem do robienia tego wyłącznie w kodzie.

+0

Może to dotyczyć przypadków, w których oddzielasz elementy karty od elementów sterujących użytkownika. Ale co z ogólnymi kontrolami, takimi jak przeglądarka plików, które są wyświetlane wiele razy? – bytecode77

+0

@ Tom L. w twojej sytuacji najlepsze, co udało mi się wymyślić, to nie ustawić kontekstu danych w kontrolce użytkownika, a następnie załadować okna zapisać właściwości z DP do zmiennych, a następnie ustawić kontekst na nowa instancja twojej maszyny wirtualnej. Następnie ustaw odpowiednie właściwości w VM i kontynuuj. Nie jest idealny, ale wykonuje swoją pracę. Chciałbym w metadanych DP określić, w jakim kontekście uzyskać powiązania. –

5

Zazwyczaj będzie to bind właściwość UserControl do właściwości ViewModel. Dwukierunkowe wiązanie działałoby w obu kierunkach, od ViewModel do widoku i na odwrót.

<Window x:Class="TestApplication.MainWindow" ...> 
    <Window.DataContext> 
     <local:MyViewModel/> 
    </Window.DataContext> 
    <Grid> 
     <local:UcTest SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/> 
    </Grid> 
</Window> 

Aby uzyskać dostęp do obiektu bezpośrednio ViewModel w powyższym przykładzie, można po prostu rzucać DataContext właściwości usercontrol do rodzaju ViewModel. DataContext jest dziedziczony z MainWindow.

var viewModel = DataContext as MyViewModel; 
var property = viewModel.MyViewModelProperty; 

Można by oczywiście również bezpośrednio przypisać specjalistycznej instancji ViewModel do UserControl za DataContext:

<local:UcTest SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/> 
    <local:UcTest.DataContext> 
     <local:UserControlViewModel/> 
    </local:UcTest.DataContext> 
</local:UcTest> 

lub można utworzyć instancji ViewModel jako zasób w słowniku zasobów i przypisać DataContext taki jak ten

<local:UcTest DataContext="{StaticResource MyUserControlViewModel}" 
       SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/> 
+0

Hm, myślę, że mogę źle cię zrozumieć. Problem polega na tym, że UserControl ma swój własny ViewModel, z którym chciałbym się połączyć. Czy uważasz, że lepiej byłoby zachować właściwości w MainViewModel i po prostu użyć UserControl bez własnego ViewModel? –

+0

To zależy od projektu aplikacji. Oba są poprawnym rozwiązaniem. Równie dobrze można przypisać właściwość DataContext UserControl. – Clemens

+1

Hm, nie .. Naprawdę nie rozumiem tego. Czy mógłbyś wysłać przykład? Ponieważ, jak tylko zmienię DataContext dla UserControl na UserControlViewModel, nie mogę przypisać więcej zmiennych, ponieważ UserControl nie wie o tych właściwościach. Jak mogę przypisać coś do "SpecialText", jeśli SpecialText nie ma DependencyProperty? –

Powiązane problemy