依赖属性UserControl绑定不起作用

时间:2015-03-03 12:31:15

标签: c# wpf xaml mvvm user-controls

我的项目是在MVVM中实现的。我有一个MainWindow,它由状态栏和tabview组成。在tabview中,有一个名为" AnnotationView"的UserControl。 Annotationview是两个较小的用户控件的父级,称为TimePicker。 TimePicker由两个文本框组成,一个用于小时,一个用于分钟。我想两次使用这个UserControl(这也是为什么我把它作为自己的控件,以后再重用它)。

TimePicker的XAML:

<UserControl x:Class="archidb.Views.TimePicker"
             x:Name="TimePickerControl"
             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" 
             mc:Ignorable="d" Height="Auto" Width="Auto"
             KeyboardNavigation.TabNavigation="Local">

    <Grid DataContext="{Binding ElementName=TimePickerControl}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="5"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBox Style="{StaticResource TextBoxStyle}"
                 Text="{Binding Path=HourValue}"
                 x:Name="tbHours"
                 KeyboardNavigation.TabIndex="0"/>
        <TextBlock Style="{StaticResource TextBlockStyle}"
                   Margin="0 -3 0 5"
                   Text=":"
                   Grid.Column="1"/>
        <TextBox Grid.Column="2" Style="{StaticResource TextBoxStyle}"
                 Text="{Binding Path=MinuteValue}"
                 x:Name="tbMinutes"
                 KeyboardNavigation.TabIndex="1"/>
    </Grid>
</UserControl>

TimePicker Code-Behind:

public partial class TimePicker : UserControl
{
    public static readonly DependencyProperty HourValueProperty = DependencyProperty.Register("HourValue", typeof(string), typeof(TimePicker), new PropertyMetadata("00"));
    public string HourValue
    {
        get { return (string)GetValue(HourValueProperty); }
        set { SetValue(HourValueProperty, value); }
    }

    public static readonly DependencyProperty MinuteValueProperty = DependencyProperty.Register("MinuteValue", typeof(string), typeof(TimePicker), new PropertyMetadata("00"));
    public string MinuteValue
    {
        get { return (string)GetValue(MinuteValueProperty); }
        set { SetValue(MinuteValueProperty, value); }
    }

    public TimePicker()
    {
        InitializeComponent();
    }
}

在AnnotationControl中,我插入UserControls,如下所示:

<v:TimePicker x:Name="tpStart"
              HourValue="{Binding Path=StartHours}"
              MinuteValue="{Binding Path=StartMinutes}"
              KeyboardNavigation.TabIndex="2"/>

<v:TimePicker x:Name="tpEnde"
              HourValue="{Binding Path=EndHours}"
              MinuteValue="{Binding Path=EndMinutes}"
              KeyboardNavigation.TabIndex="3"
              Grid.Row="2"/>

AnnotationControl的DataContext设置为viewmodel,我在其中声明了属性。

问题是,绑定无效。我在依赖项属性中设置的默认值(&#34; 00&#34;)没有显示在任何文本框中。此外,如果我在文本框中写入内容,AnnotationControl的viewmodel中的属性不会更改其值。这个问题已经困扰了我好几天了,我在这里做错了什么?

3 个答案:

答案 0 :(得分:2)

解决方案是在UserControl中使用RelativeSource Binding,然后不将DataContext设置为自身

在你的控制中:

<TextBox Style="{StaticResource TextBoxStyle}" Text="{Binding HourValue, RelativeSource=
    {RelativeSource AncestorType={x:Type YourPrefixToBeAdded:TimePickerControl}}}"
    x:Name="tbHours" KeyboardNavigation.TabIndex="0" />
<TextBlock Style="{StaticResource TextBlockStyle}" Margin="0 -3 0 5" Text=":" 
    Grid.Column="1" />
<TextBox Grid.Column="2" Style="{StaticResource TextBoxStyle}" Text="{Binding 
    MinuteValue, RelativeSource={RelativeSource AncestorType={x:Type 
    YourPrefixToBeAdded:TimePickerControl}}}" x:Name="tbMinutes" 
    KeyboardNavigation.TabIndex="1" />

然后,您将能够从控件外部绑定属性数据。

答案 1 :(得分:0)

首先,在UserControl构造函数中,将DataContext设置为自身:

public TimePicker()
{
   InitializeComponent();

   this.DataContext = this;
}

此外,在用户控件中将其从网格中删除:

DataContext="{Binding ElementName=TimePickerControl}"

用户控件的DataContext已在用户控件中设置,因此当您使用以下代码时:

HourValue="{Binding Path=EndHours}"

您实际上是在询问“在UserControl的DataContext中绑定到EndHours。”

您需要更改绑定,以便查看父窗口的DataContext。为父窗口指定名称并使用以下内容:

HourValue="{Binding DataContext.EndHours, ElementName=windowName}"

答案 2 :(得分:0)

最简单的方法: 删除该行:

DataContext="{Binding ElementName=TimePickerControl}"

这样绑定:

"{Binding ElementName=TimePickerControl, Path=HourValue}"

另一种方式:(清洁)

在TimePicker构造函数中设置它:

  (this.Content as FrameworkElement).DataContext = this;

这样绑定:

"{Binding HourValue}"

经过一些阅读后,您的示例应该正常工作,因此我假设您没有为ViewModel实现INotifyPropertyChanged,&#34; 00&#34;未显示,因为绑定工作,属性设置为默认值,其值不会更新。