我的UserControl中的DependencyProperty无法更新ViewModel中的绑定属性

时间:2010-12-17 12:28:34

标签: c# wpf data-binding xaml wpf-controls

我创建了一个包含带有一些自定义行为的TextBox的usercontrol,我想将Text属性绑定到ViewModel中的属性。

我已将问题隔离到示例解决方案中并设法使用ViewModel属性值更新Text属性,但是当我写入文本框并离开文本框时,我的Person.Name属性未更新。

我的usercontrol xaml:

<UserControl x:Class="WpfCustomUserControlBinding.TextBoxReadOnlyLooksDisabled"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Control.Resources>
    <Style x:Key="readOnlyTextbox">
        <Style.Triggers>
            <Trigger Property="TextBoxBase.IsReadOnly" Value="True">
                <Setter Property="TextBoxBase.Background" Value="WhiteSmoke" />
                <Setter Property="TextBoxBase.Foreground" Value="#FF6D6D6D" />
                <Setter Property="TextBox.BorderBrush" Value="DarkGray" />
                <Setter Property="TextBoxBase.BorderThickness" Value="1,1,1,1" />
            </Trigger>
            <Trigger Property="TextBoxBase.IsReadOnly" Value="False">
                <Setter Property="TextBoxBase.Background" Value="White" />
                <Setter Property="TextBoxBase.Foreground" Value="Black" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Control.Resources>

<TextBox Style="{StaticResource readOnlyTextbox}" x:Name="txtTextBoxBase" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />

代码隐藏代码:

public partial class TextBoxReadOnlyLooksDisabled
{
    public TextBoxReadOnlyLooksDisabled()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof (string)
                                                                                         , typeof (TextBoxReadOnlyLooksDisabled)
                                                                                         ,new PropertyMetadata(OnTextChange));

    private static void OnTextChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var textBoxReadOnlyLooksDisabled = (TextBoxReadOnlyLooksDisabled) d;
        textBoxReadOnlyLooksDisabled.txtTextBoxBase.Text = (string) e.NewValue;
    }

    public string Text
    {
        get { return (string) GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
}

我尝试让样本运行的窗口:

<Window x:Class="WpfCustomUserControlBinding.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:src="clr-namespace:WpfCustomUserControlBinding" Title="MainWindow" Height="153" Width="525">
<Window.Resources>
    <src:Person x:Key="myDataSource"/>        
</Window.Resources>
<Grid >
    <Label Content="Plain vanilla" Height="26" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" Width="143" />
    <Label Content="Messed up version" Height="26" HorizontalAlignment="Left" Margin="12,61,0,0" Name="label2" VerticalAlignment="Top" Width="143" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="152,15,0,0" x:Name="txtVanlig" VerticalAlignment="Top" Width="251" Text="{Binding Source={StaticResource myDataSource}, Path=Name, Mode=TwoWay}"/>

    <src:TextBoxReadOnlyLooksDisabled Height="23" HorizontalAlignment="Left" Margin="152,61,0,0" x:Name="txtVrien" VerticalAlignment="Top" Width="251" Text="{Binding Source={StaticResource myDataSource}, Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

样本值类:

 public class Person
{
    private string _name = "King Chaos";

    public string Name{get{return _name;}set{_name = value;}}
}

提前致谢。 ;)

编辑:添加INotifyPropertyChanged不起作用,因为更新自定义TextBox时不会访问Name的set方法。

3 个答案:

答案 0 :(得分:4)

问题是TextBoxReadOnlyLooksDisabled UserControl中的TextBox没有与Text属性的双向绑定 - 您只在属性值更改时以编程方式(在OnTextChanged处理程序中)更新TextBox,反之则不然。

为什么不完全删除已更改的处理程序,而是添加绑定,如下所示:

<UserControl x:Class="WpfCustomUserControlBinding.TextBoxReadOnlyLooksDisabled"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Control.Resources>        
  //...
</Control.Resources>

<TextBox Style="{StaticResource readOnlyTextbox}"
         x:Name="txtTextBoxBase"
         HorizontalAlignment="Stretch"
         VerticalAlignment="Stretch"
         Text="{Binding Path=Text, Mode=TwoWay}"/>

不要忘记也相应地设置DataContext:

public partial class TextBoxReadOnlyLooksDisabled : UserControl
{
    public TextBoxReadOnlyLooksDisabled()
    {
        InitializeComponent();
        DataContext = this;
    }

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string),
                                                                                         typeof(TextBoxReadOnlyLooksDisabled));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
}

答案 1 :(得分:1)

您遇到的问题是因为自定义TextTextBox的{​​{1}}依赖项属性实际上并未绑定到您的“ViewModel”({1当你在TextBoxReadOnlyLooksDisabled中写一些内容时,Person dp被更改,但更改不会传播回ViewModel。 您可以执行的操作是将嵌套txtTextBoxBase的{​​{1}} dp连接到自定义控件的Text dp:

Text

答案 2 :(得分:-2)

public class Person : INotifyPropertyChanged
{ 
    public event PropertyChangedEventHandler PropertyChanged;

    private string _name = "King Chaos"; 

    public string Name{
       get{
          return _name;
       }
       set{
          _name = value;
          if (PropertyChanged != null)
              PropertyChanged(this, new 
                 PropertyChangedEventArgs("Name"));
       }
    } 
} 

只要您的模型必须实现INotifyPropertyChanged并在设置属性时更改属性,以便XAML检测到更改并刷新其值。