2014-07-10 14 views
5

Jestem początkującym z xaml (dla PODEJŚCIA MVVM) za pomocą Silverlight. Przeczytałem kilka dokumentów i jestem nieco zdezorientowany. Byłbym bardzo wdzięczny, gdyby ktoś mógł wyjaśnić różnicę między następującymi.Różnica terminów xaml używanych do wiązania

Załóżmy mój XAML jest:

xmlns:viewmodel="clr-namespace:smallMVVM" 
    ...... 
    ...... 
<UserControl.Resources> 
     <viewmodel:ViewModel x:Key="ViewModel"/> 
     <viewmodel:DatetimeToDateConverter x:Key="MyConverter"/> 
</UserControl.Resources> 

Teraz jaka jest różnica pomiędzy:

  1. mam na myśli MainPage.cs jeśli robię "this.DataContext = new ViewModel();". I na MainPage.xaml, jeśli wykonam następujące <Grid DataContext="{Binding Source={StaticResource ViewModel}}">. Czy jest jakaś różnica między tymi dwoma?

  2. Gdzieś widziałem ItemsSource="{StaticResource customers}" w niektórych przykładach. Czym różni się ItemSource od DataContext. Podczas gdy widzę w przykładzie (1), że mam to samo w Binding of DataContext (zobacz: Source={StaticResource ViewModel} iw (2) jest on zastąpiony przez customers). Jak są dwa różne?

  3. Czasami widzę również bezpośrednio ItemsSource="{Binding Students}" wewnątrz nie ma. Czym się różni od StaticResource?

  4. Niektóre przykłady mają po prostu Binding="{Binding Name}".

  5. Czym różnią się SelectedItem i SelectedValue?

Czy ktoś mógłby wyjaśnić im mały i prosty przykład? W wyszukiwaniu internetowym można znaleźć typowe przykłady dla początkujących.

Odpowiedz

1

1) Technicznie nie ma żadnej różnicy pomiędzy tymi dwoma deklaracjami kontekstu danych lubię to robić w opóźnieniem kodu, który wygląda tak:

Partial Public Class MainPage 
    Inherits UserControl 

    Private _viewModel As TestViewModel 

    Public Sub New() 
     InitializeComponent() 
     _viewModel = TryCast(Resources("TheViewModel"), TestViewModel) 
     Me.DataContext = _viewModel 
    End Sub 
End Class 

2) Nie chcesz aby ustawić swój ItemsSource na Static Page Resource, chcesz ustawić go na właściwość w swoim ViewModel. Poniżej znajduje się przykładowy widok i ViewModel, zwróć uwagę na Dziedziczenie i Impelenty na maszynie wirtualnej, Pozwalają one twojej maszynie wirtualnej na informowanie Twojego Widoku o zmianie właściwości i przeładowaniu właściwości.

Widok:

<UserControl x:Class="SilverlightTestApp.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 
d:DesignHeight="300" d:DesignWidth="400" 
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" 
xmlns:ModelViewModel="clr-namespace:SilverlightTestApp" > 

<UserControl.Resources> 
    <ModelViewModel:TestViewModel x:Key="TheViewModel" /> 
</UserControl.Resources> 

<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource TheViewModel}"> 
    <ItemsControl ItemsSource="{Binding SampleCollection}"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding}"></TextBlock> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</Grid> 

ViewModel:

Imports System.ComponentModel 
Imports System.Collections.ObjectModel 
Public Class TestViewModel 
    Inherits DependencyObject 
    Implements System.ComponentModel.INotifyPropertyChanged 
    Implements INotifyDataErrorInfo 

    Private _model As TestModel 

    Sub New() 
     Me.New(New TestModel) 
    End Sub 

    Public Sub New(ByVal model As TestModel) 
     _model = model 

     _sampleCollection = New ObservableCollection(Of String) 
     _sampleCollection.Add("one") 
     _sampleCollection.Add("two") 
     _sampleCollection.Add("three") 
     _sampleCollection.Add("four") 

    End Sub 

    Private _sampleCollection As ObservableCollection(Of String) 
    Public Property SampleCollection As ObservableCollection(Of String) 
     Get 
      Return _sampleCollection 
     End Get 
     Set(value As ObservableCollection(Of String))    
      If value IsNot Nothing Then 
       _sampleCollection = value 
      End If 
      Me.OnPropertyChanged("SampleCollection") 

     End Set 
    End Property 

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged 

    Protected errors As New Dictionary(Of String, List(Of String)) 

    Protected Sub OnPropertyChanged(ByVal propertyName As String) 
     RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName)) 
    End Sub 

    ' #Region " Validation Plumbing" 
    ' Adds the specified error to the errors collection if it is not 
    ' already present, inserting it in the first position if isWarning is 
    ' false. Raises the ErrorsChanged event if the collection changes. 
    Public Sub AddError(ByVal propertyName As String, ByVal [error] As String, 
         ByVal isWarning As Boolean) 

     If Not errors.ContainsKey(propertyName) Then _ 
      errors(propertyName) = New List(Of String)() 

     If Not errors(propertyName).Contains([error]) Then 
      If isWarning Then 
       errors(propertyName).Add([error]) 
      Else 
       errors(propertyName).Insert(0, [error]) 
      End If 
      RaiseErrorsChanged(propertyName) 
     End If 

    End Sub 

    ' Removes the specified error from the errors collection if it is 
    ' present. Raises the ErrorsChanged event if the collection changes. 
    Public Sub RemoveError(ByVal propertyName As String, ByVal [error] As String) 

     If errors.ContainsKey(propertyName) AndAlso 
      errors(propertyName).Contains([error]) Then 

      errors(propertyName).Remove([error]) 
      If errors(propertyName).Count = 0 Then errors.Remove(propertyName) 
      RaiseErrorsChanged(propertyName) 

     End If 

    End Sub 
    Public Sub RemoveError(ByVal propertyName As String) 

     If errors.ContainsKey(propertyName) Then 

      errors.Remove(propertyName) 
      RaiseErrorsChanged(propertyName) 

     End If 

    End Sub 

    Public Sub RaiseErrorsChanged(ByVal propertyName As String) 
     OnPropertyChanged("HasErrors") 
     RaiseEvent ErrorsChanged(Me, 
      New DataErrorsChangedEventArgs(propertyName)) 
    End Sub 

    Public Event ErrorsChanged As EventHandler(Of DataErrorsChangedEventArgs) _ 
     Implements INotifyDataErrorInfo.ErrorsChanged 

    Public Function GetErrors(ByVal propertyName As String) _ 
     As System.Collections.IEnumerable _ 
     Implements INotifyDataErrorInfo.GetErrors 

     If (String.IsNullOrEmpty(propertyName) OrElse 
      Not errors.ContainsKey(propertyName)) Then Return Nothing 
     Return errors(propertyName) 

    End Function 

    Public ReadOnly Property HasErrors As Boolean _ 
     Implements INotifyDataErrorInfo.HasErrors 
     Get 
      Return errors.Count > 0 
     End Get 
    End Property 

End Class 

Powyższy kluczowym elementem jest Me.OnPropertyChanged("SampleCollection") który opowiada View, aby zaktualizować właściwości jest on związany.

Uwaga na temat architektury, jeśli budujesz aplikację z wieloma widokami i ViewModels, utwórz ViewModelBase i dziedzicz jej DependencyObject i Implementuj INotifyPropertyChanged, wtedy wszystkie modele widoku rzeczywistego mogą dziedziczyć z ViewModelBase.

Utworzyłem również klasę o nazwie TestModel, która jest używana w maszynie wirtualnej, ale pozostawiła ją pustą. Model jest tam, gdzie umieścisz kod do rozmowy z DB, lub co robię, wywołaj usługę WCF, która komunikuje się z moim DB.

5) Wreszcie SelectedItem jest rzeczywistym obiektem w wybranym źródle pozycji, podczas gdy SelectedValue jest wartością SelectedValuePath. W powyższym przykładzie utworzyłem prostą kolekcję String, ale mówię, że masz kolekcję niestandardowych obiektów, które mają wiele właściwości, możesz określić SelectedValuePath jako jedną z tych właściwości. SelectedItem zwróci cały obiekt.