Binding Silverlight 3 description attribute of dataInput:DescriptionViewer
Silverlight's dataInput:Label and dataInput:DescriptionViewer controls provide a useful function through their ability to bind to a TextBox. Rather than hard-coding the text content of my labels and descriptions with System.ComponentModel.DataAnnotations.DisplayAttribute, I'd prefer to bind these attributes to properties of a class that holds admin-editable text. This works for Label, but not for DescriptionViewer.
Specifically, this Label works:
<dataInput:Label Grid.Row="00" Grid.Column="0"
Target="{Binding ElementName=inpStatus}"
Content="{Binding StatusLabel}" IsRequired="true" />
but this DescriptionViewer is invisible:
<dataInput:DescriptionViewer Grid.Row="00" Grid.Column="3"
Target="{Binding ElementName=inpStatus}"
Name="dvBound2" Description="{Binding Path=StatusDescription}" />
When I remove the binding to my TextBox, the DescriptionViewer is shown:
<dataInput:DescriptionViewer Grid.Row="00" Grid.Column="2"
Name="dvBound1" Description="{Binding Path=StatusDescription}" />
Should it be possible to bind a DescriptionViewer to both a TextBox and an alternate Description source?
Thanks in advance!
MainPage.xaml:
<UserControl x:Class="DataInputDem开发者_StackOverflowo.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"
xmlns:controlsToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"
xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="142"></ColumnDefinition>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="24"></ColumnDefinition>
<ColumnDefinition Width="24"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<dataInput:Label Grid.Row="00" Grid.Column="0"
Target="{Binding ElementName=inpStatus}"
Content="{Binding StatusLabel}" IsRequired="true" />
<TextBox Grid.Row="00" Grid.Column="1"
Text="{Binding Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True, Path=Status}"
Name="inpStatus" MaxLength="025"
BindingValidationError="_BindingValidationError" />
<dataInput:DescriptionViewer Grid.Row="00" Grid.Column="2"
Name="dvBound1" Description="{Binding Path=StatusDescription}" />
<!-- Following DescriptionViewer is not shown. -->
<dataInput:DescriptionViewer Grid.Row="00" Grid.Column="3"
Target="{Binding ElementName=inpStatus}"
Name="dvBound2" Description="{Binding Path=StatusDescription}" />
<dataInput:ValidationSummary Grid.Row="01" Grid.Column="0"
Grid.ColumnSpan="4" Name="VS1" />
</Grid>
</UserControl>
MainPage.xaml.vb:
Partial Public Class MainPage
Inherits UserControl
Public myDataClass = New DataClass
Public Sub New()
InitializeComponent()
myDataClass.status = "Default Status"
myDataClass.StatusLabel = "Status Label"
myDataClass.StatusDescription = "Status Description"
LayoutRoot.DataContext = myDataClass
End Sub
Private Sub _BindingValidationError(ByVal sender As Object, ByVal e As ValidationErrorEventArgs)
End Sub
End Class
DataClass.vb:
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Runtime.Serialization
Imports System.ComponentModel.DataAnnotations
Imports System.Windows.Controls
Public Class DataClass
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Private Sub NotifyPropertyChanged(ByVal info As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub
Function ValidateEntry(ByVal fieldname As String, ByRef value As Object) As Object
Dim ctx As New ValidationContext(Me, Nothing, Nothing)
ctx.MemberName = fieldname
Validator.ValidateProperty(value, ctx)
Return value
End Function
<DataMember()> _
<Required()> _
<StringLength(100)> _
Public Property Status() As String
Get
Return _Status
End Get
Set(ByVal value As String)
_Status = ValidateEntry("Status", value)
NotifyPropertyChanged("")
End Set
End Property
Private _Status As String
<DataMember()> _
Public Property StatusLabel() As String
Get
Return _StatusLabel
End Get
Set(ByVal value As String)
_StatusLabel = value
NotifyPropertyChanged("")
End Set
End Property
Private _StatusLabel As String
<DataMember()> _
Public Property StatusDescription() As String
Get
Return _StatusDescription
End Get
Set(ByVal value As String)
_StatusDescription = value
NotifyPropertyChanged("")
End Set
End Property
Private _StatusDescription As String
End Class
I had the exact same problem with the DescriptionViewer using this markup:
<TextBox x:Name="UserNameTextBox" Text="{Binding UserName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="1"></TextBox>
<dataInput:DescriptionViewer Target="{Binding ElementName=UserNameTextBox}" Description="{Binding Path=CreateUserResources.UserNameDescription, Source={StaticResource GlobalResources}}" Grid.Column="2" Grid.Row="1"></dataInput:DescriptionViewer>
Before binding the Description to its resource it was a plain string in the markup and it did work.
To resolve the problem I have set the PropertyPath of the DescriptionViewer with the property name where the binding is located on the Target control. It is now working correctly.
<TextBox x:Name="UserNameTextBox" Text="{Binding UserName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="1"></TextBox>
<dataInput:DescriptionViewer Target="{Binding ElementName=UserNameTextBox}" PropertyPath="Text" Description="{Binding Path=CreateUserResources.UserNameDescription, Source={StaticResource GlobalResources}}" Grid.Column="2" Grid.Row="1"></dataInput:DescriptionViewer>
If you are using MVVM make sure the PropertyPath does not match a property of your presenter model. I did not investigate but I had an instance where I was forced to change the property name of my presenter to make it work. Seems like the control was trying to parse the metadata from the property of my presenter instead of the target control.
Hope this help.
精彩评论