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.