I am a beginner with xaml (for MVVM APPROACH) using Silverlight. I read several documents and am a bit confused about it all. I would really appreciate if someone could explain the difference between the following.
Suppose my XAML is:
xmlns:viewmodel="clr-namespace:smallMVVM"
......
......
<UserControl.Resources>
<viewmodel:ViewModel x:Key="ViewModel"/>
<viewmodel:DatetimeToDateConverter x:Key="MyConverter"/>
</UserControl.Resources>
Now what is the difference between:
I mean in MainPage.cs if I do "this.DataContext = new ViewModel();"
. And in MainPage.xaml if I do the following <Grid DataContext="{Binding Source={StaticResource ViewModel}}">
. Is there any difference between the two ?
Somewhere I saw ItemsSource="{StaticResource customers}"
in some example. How is ItemSource
different from DataContext
. Whereas I can see in the example (1)
that I have same inside the Binding of DataContext (please see this: Source={StaticResource ViewModel}
and in (2)
it is replaced with customers
). How are the two different?
Sometimes I also see directly ItemsSource="{Binding Students}"
there is no StaticResource
inside. How is it different from with StaticResource?
Some examples have simply Binding="{Binding Name}"
.
How are SelectedItem
and SelectedValue
different?
Could someone please explain them with a small and simple example ? On internet search there are typical examples for a beginner to understand.
1) Technically there is no difference between the two declarations of the Data Context I like to do it in the code-behind, which looks like this:
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)You don't want to set your ItemsSource to a Static Page Resource, you want to set it to a Property in your ViewModel. Below is a sample View and ViewModel, notice the Inherits and Impelments on the VM, These allow your VM to tell your View that properties have changed, and to reload the property.
View:
<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
The key piece above is Me.OnPropertyChanged("SampleCollection")
which tells the View to update the property it is bound to.
A note on architecture, if you are building an application with multiple Views and ViewModels, create a ViewModelBase and have it inherit DependencyObject and Implement INotifyPropertyChanged, then all of your real view models can Inherit from the ViewModelBase.
I also created a class called TestModel that is used in the VM, but left it empty. The model is where you put the code to talk to the DB, or what I do, call a WCF Service that talks to my DB.
5) Finally, the SelectedItem is the actual object within the ItemSource that is selected, whereas SelectedValue is the value of SelectedValuePath. In the example above, I've created a simple collection of String, but say you have a collection of custom objects that have multiple properties, you can specify the SelectedValuePath as one of those properties. The SelectedItem would return the entire object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With