This blog entry uses Visual Basic because the problem it solves doesn't exist in C#.
This time last year I wrote a blog entry about the perils of passing data row fields to SetProperty in the MVVM model. A colleague recently asked me about a problem he was having when passing an object's property to SetProperty - the symptoms were very similar.
In his situation he had a class called ClientServer that contained properties and was passed between the client and the server. It did not implement INotifyPropertyShared. Then he had a wrapper class called Client that had an instance of ClientServer as a private member and used it as backing store for properties in Client that did implement INotifyPropertyChanged.
The bound control was always showing the prior value of the property instead of the current value. His Prop property in Client looked like this...
Get
Return ClientServer.Prop
End Get
Set(value As String)
SetProperty(ClientServer.Prop, value)
End Set
End Property
If (Object.Equals(storage, value)) Then Return False
storage = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Function
Get
Return ClientServer.Prop
End Get
Set(value As String)
SetProperty(ClientServer, value)
End Set
End Property
Dim PI As PropertyInfo = type.GetProperty(name)
If Object.Equals(PI.GetValue(storage), value) Then Return False
PI.SetValue(storage, value, Nothing)
Else
If (Object.Equals(storage, value)) Then Return False
storage = Convert.ChangeType(value, type)
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
Return True
End Function
Replace the contents of MainWindow.xaml with this...
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"
xmlns:local="clr-namespace:ObjectBoxingVB"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="Object Boxing" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Prop Bound Right"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Prop Bound Wrong"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Client.Prop}" Width="100" Background="Tan"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Client.PropDoneWrong}" Width="100" Background="Tan"/>
</Grid>
</Window>
Public Property Prop As String = ""
Public Property PropDoneWrong As String = ""
End Class
Implements INotifyPropertyChanged
Get
Return ClientServer.Prop
Set(value As String)
End Set
End Property
Get
Return ClientServer.PropDoneWrong
Set(value As String)
End Set
End Property
Dim type As Type = storage.GetType()
If Object.Equals(PI.GetValue(storage), value) Then Return False
PI.SetValue(storage, value, Nothing)
If (Object.Equals(storage, value)) Then Return False
storage = Convert.ChangeType(value, type)
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Function
End Class
Inherits Window
Public Property SomeText As String
Get
Return _SomeText
Set(value As String)
Client.Prop = SomeText
Client.PropDoneWrong = SomeText
End Set
End Property
End Sub
End Namespace
No comments:
Post a Comment