2011-04-29 20 views
5

Próbuję nauczyć się korzystać z wiązania WPF i architektury MVVM. Mam problemy z Właściwościami Dependency. Próbowałem kontrolować widoczność elementu w widoku, wiążąc go z DependencyProperty w DataContext, ale to nie działa. Bez względu na to, jak ustawię wartość GridVisible w konstruktorze poniższego modelu widoku, jest on zawsze wyświetlany jako widoczny po uruchomieniu kodu.Architektura wiązania danych WPF Pytanie

Czy ktoś może zobaczyć, gdzie się źle dzieje?

kod C# (ViewModel):

public class MyViewModel : DependencyObject 
{ 
    public MyViewModel() 
    { 
     GridVisible = false; 
    } 

    public static readonly DependencyProperty GridVisibleProperty = 
    DependencyProperty.Register(
     "GridVisible", 
     typeof(bool), 
     typeof(MyViewModel), 
     new PropertyMetadata(false, 
       new PropertyChangedCallback(GridVisibleChangedCallback))); 

    public bool GridVisible 
    { 
     get { return (bool)GetValue(GridVisibleProperty); } 
     set { SetValue(GridVisibleProperty, value); } 
    } 

    protected static void GridVisibleChangedCallback(
     DependencyObject source, 
     DependencyPropertyChangedEventArgs e) 
    { 
     // Do other stuff in response to the data change. 
    } 
} 

kod XAML (Widok):

<UserControl ... > 

    <UserControl.Resources> 
     <BooleanToVisibilityConverter x:Key="BoolToVisConverter" /> 
    </UserControl.Resources> 

    <UserControl.DataContext> 
     <local:MyViewModel x:Name="myViewModel" /> 
    </UserControl.DataContext> 

    <Grid x:Name="_myGrid" 
     Visibility="{Binding Path=GridVisible, 
      ElementName=myViewModel, 
      Converter={StaticResource BoolToVisConverter}}"> 

     <!-- Other elements in here --> 

    </Grid> 

</UserControl> 

Szukałem w kilku samouczki online, a wydaje się, że jestem poprawnie podążając za tym, co tam znalazłem. Jakieś pomysły? Dzięki!

Odpowiedz

2

Usuń ElementName z wiązania, co nie wydaje się być poprawne. Zmień go na adres:

<Grid x:Name="_myGrid" 
     Visibility="{Binding Path=GridVisible, 
      Converter={StaticResource BoolToVisConverter}}"> 
+0

Właściwie skopiowałem Twój kod i stwierdziłem, że działało z wiązaniem zi bez elementu ElementName. Do czego używasz kontrolki użytkownika (np. Okna lub innej kontroli użytkownika)? Być może coś jest nie tak (kod, którego nie uwzględniłeś). – thornhill

+0

Usunąłem elementName i nadal nie działa. Wygląda jednak na to, że masz rację - prawdopodobnie ma to coś wspólnego z inną częścią mojego kodu, a nie z odkażoną wersją zamieszczoną powyżej. Niestety nie mogę opublikować rzeczywistego kodu, ponieważ jest on przeznaczony do pracy. – RobotNerd

+0

W takim przypadku, gdy używasz aplikacji i masz otwarte okno, które zawiera tę kontrolę użytkownika, zajrzyj do okna wyjściowego w VisualStudio w poszukiwaniu błędów z tekstem podobnym do tego "Błąd ścieżki BindingExpression: właściwość" GridVisible "nie została znaleziona na "object ......" Treść tego komunikatu może pomóc w dalszym debugowaniu. Przepraszam, nie mogę ci pomóc. powodzenia. – thornhill

0

Punktem ustawiania ViewModel jako DataContext ma umożliwić łatwe względne powiązania, wszystkie wiązania, gdzie tylko określające Path wziąć DataContext jako źródła, które jest dziedziczona przez cały UserControl (chyba że jest ustawić inaczej, na przykład w szablonach przedmiotów ItemsControl)

Tak więc po ustawieniu DataContext w UserControl zwykle nie określa się żadnego źródła podczas wiązania z maszyną wirtualną. (Źródła są ElementName, RelativeSource i Source)

Dalsze Ja osobiście nie stałaby ViewModels dziedziczą DependencyObject ponieważ wprowadza nitki powinowactwo, a także punkt DependencyProperties robi rzadkie struktury danych bardziej wydajne, nie tworząc zbędnych pól we wszystkich ich (ViewModels zwykle są przeciwieństwem rzadkich).

+3

'INotifyPropertyChanged' jest alternatywą dla' DependencyObject' - większość viewmodeli używa tej właściwości zamiast zależności. –

1

Czy Twój ViewModel zaimplementował INotifyPropertyChanged zamiast dziedziczyć z DependencyObject. Zaimplementuj interfejs i podnieś PropertyChanged z ustawiacza dla właściwości.

private bool gridVisible; 

    public bool GridVisible 
    { 
     get { return gridVisible; } 
     set 
     { 
      gridVisible = value; 
      OnPropertyChanged("GridVisible"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
+1

Nie musisz odwoływać się do swojej maszyny wirtualnej w swoim XAML z ElementName, ani nie musisz nazywać swojej maszyny wirtualnej. Po przypisaniu go do usercontrol.DataContext staje się domyślnym źródłem wiązania dla wszystkich dzieci kontrolki użytkownika. –

Powiązane problemy