Usercontrol中的Usercontrol与数据绑定

时间:2016-07-25 17:00:00

标签: wpf vb.net xaml user-controls

我构建了一个简单的WPF UserControl,我想在另一个UserControl中实现几个,同时保持数据绑定。我有一个简单的Debug1窗口,它实现了(1)一个绑定的文本块(仅用于验证数据绑定)&按钮; (2)具有绑定的NumericUpDownBox用户控件的单个实例; (3)包含子用户控件NumericUpDownBox实例的父用户控件的实例。

项目(1)和(2)正在运作。第(3)项没有。我觉得我在父用户控件代码的实现中遗漏了一些东西?我也遇到了一些与我有关的错误(见下文)。

Debug1 Window xaml:

<Window x:Class="Debug1"
    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:CFIT"
    mc:Ignorable="d"
    Title="Debug1" Height="225" Width="600"
    Closing="ClosingDebug1">
<Grid>
    <StackPanel Grid.Row="0" Orientation="Horizontal">
        <Button Name="NextButton" Content="Next" Click="ClickNext" Width="50" />
        <TextBox Text="{Binding Path=Years, Mode=TwoWay}" />
    </StackPanel>
    <local:NumericUpDownBox Grid.Row="1"  x:Name="SingleBox" Label="TBD" Increment="2" Value="{Binding Path=Years}"/>
    <local:YMDH_TimeControl Grid.Row="2" x:Name="TimeControl" YearsValue="{Binding Path=Years}" />
</Grid>
</Window>

调试窗口VB代码:

Public Class Debug1
    Public Mat As New clsMaterial
    Sub New()  ' Removed for brevity
    End Sub
    Private Sub ClickNext(sender As Object, e As RoutedEventArgs)
        Mat.Lives(0).MSDateOffset.Years = Mat.Lives(0).MSDateOffset.Years + 5
    End Sub
End Class

Parent UserControl xaml:

<UserControl x:Class="YMDH_TimeControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:CFIT"
         mc:Ignorable="d" 
         d:DesignHeight="50" d:DesignWidth="200" MinHeight="30" MinWidth="160"
         Name="YMDH_TimeControl">
<Grid DataContext="{Binding ElementName=YMDH_TimeControl}">
    <local:NumericUpDownBox Grid.Column="0" x:Name="Years"/>
</Grid>
</UserControl>

父UserControl VB代码:

Public Class YMDH_TimeControl
Public Shared ReadOnly YearsValueProperty As DependencyProperty = DependencyProperty.Register("YearsValue", GetType(Integer), GetType(YMDH_TimeControl), New FrameworkPropertyMetadata(0, (FrameworkPropertyMetadataOptions.BindsTwoWayByDefault), Nothing, New CoerceValueCallback(AddressOf OnValueChanged)))

Private Shared Function OnValueChanged(d As DependencyObject, value As Object) As Object
    If IsNumeric(value) Then
        Return CInt(value)
    Else
        Return Nothing
    End If
End Function

Public Property YearsValue As Integer
    Get
        Return Years.Value
    End Get
    Set(value As Integer)
        Years.Value = value
    End Set
End Property
End Class

Child UserControl xaml:

<UserControl x:Class="NumericUpDownBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:CFIT"
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="50" MinHeight="30" MinWidth="40"
             Name="NumericUpDownBox">
    <Grid DataContext="{Binding ElementName=NumericUpDownBox}">
        <Grid.Resources>
            ... removed for brevity...
        </Grid.Resources>
        <!--Box Definition-->
        <Border Style="{StaticResource SectionNameBorder}" Grid.Column="0">
            <Grid Background="Gray" >
                <Viewbox>
                    <TextBlock Name="LabelTextBlock" Text="{Binding Path=Label, ElementName=NumericUpDownBox}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                </Viewbox>
                <Grid Grid.Row="2" Background="White" >
                    <Grid Grid.Column="0" HorizontalAlignment="Right">
                        <Viewbox>
                            <TextBox Name="ValueTextBox" BorderBrush="White" Text="{Binding Path=Value, Mode=TwoWay, ElementName=NumericUpDownBox, UpdateSourceTrigger=PropertyChanged}" />
                        </Viewbox>
                    </Grid>
                    <Grid Grid.Column="1">
                        <RepeatButton Name="UpArrow" Style="{StaticResource UpArrowStyle}" Tag="+" Click="TickValues" />
                        <RepeatButton Name="DownArrow" Style="{StaticResource DownArrowStyle}" Tag="-" Click="TickValues" />
                    </Grid>
                </Grid>
            </Grid>
        </Border>
     </Grid>
</UserControl>

Child UserControl VB代码:

Public Class NumericUpDownBox
    Private Const DefaultInc As Integer = 1
    Public Sub New()
        InitializeComponent()
        If Increment = 0 Then Increment = DefaultInc
    End Sub
    Private Sub TickValues(sender As Object, e As RoutedEventArgs)
        Dim Sign As Char
        Dim Tag As String
        Tag = sender.tag.ToString
        If Len(Tag) = 0 Then Exit Sub
        Sign = Left(Tag, 1)
        If Sign = "+" Then
            Value = Value + Increment
        ElseIf Sign = "-" Then
            Value = Value - Increment
        End If
    End Sub
    Public Property Value As Integer
        Get
            Return CInt(GetValue(ValueProperty))
        End Get
        Set(value As Integer)
            If value < 0 Then value = 0
            SetValue(ValueProperty, value)
        End Set
    End Property
    Public Property Label As String
        Get
            Return GetValue(LabelProperty)
        End Get
        Set(value As String)
            SetValue(LabelProperty, value)
        End Set
    End Property
    Public Property Increment As Integer
        Get
            Return CInt(GetValue(IncProperty))
        End Get
        Set(value As Integer)
            If value < 0 Then value = 0
            SetValue(IncProperty, value)
        End Set
    End Property
    Public Shared ReadOnly ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(Integer), GetType(NumericUpDownBox), New FrameworkPropertyMetadata(0, (FrameworkPropertyMetadataOptions.BindsTwoWayByDefault), Nothing, New CoerceValueCallback(AddressOf OnValueChanged)))
    Public Shared ReadOnly LabelProperty As DependencyProperty = DependencyProperty.Register("Label", GetType(String), GetType(NumericUpDownBox), New FrameworkPropertyMetadata(""))
    Public Shared ReadOnly IncProperty As DependencyProperty = DependencyProperty.Register("Increment", GetType(Integer), GetType(NumericUpDownBox), New FrameworkPropertyMetadata(0, Nothing, New CoerceValueCallback(AddressOf OnValueChanged)))
    Private Shared Function OnValueChanged(d As DependencyObject, value As Object) As Object
        If IsNumeric(value) Then
            Return CInt(value)
        Else
            Return Nothing
        End If
    End Function
End Class

输出窗口中的示例信息错误:

  

System.Windows.Data信息:10:无法使用绑定检索值,并且不存在有效的回退值;使用默认值。 BindingExpression:路径=岁;的DataItem = NULL;目标元素是&#39; YMDH_TimeControl&#39; (名称=&#39; TimeControl&#39);目标财产是“年度值”&#39; (键入&#39; Int32&#39;)

如何让我的数据绑定通过我的父用户控件?

0 个答案:

没有答案