1

我想创建一个用户控件,它本质上是一个带有文本框的标签。现在我希望能够绑定TextBox.Text到不同的值。

为此,我在我的 UserControl 中创建了一个 DependencyProperty,现在正尝试将某些内容绑定到新创建的 DependencyProperty,但文本似乎没有得到更新。

我的 UserControl1.xaml 看起来像这样:

<UserControl x:Class="WpfApplication1.UserControl1"
         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" 
         d:DesignHeight="48" d:DesignWidth="200">
<Grid>
    <WrapPanel Height="48" HorizontalAlignment="Left" Name="wrapPanel1" VerticalAlignment="Top" Width="200">
        <Label Content="Label" Height="48" Name="label1" Width="100" />
        <TextBox Height="48" Name="textBox1" Width="100"  />
    </WrapPanel>
</Grid>

我的 UserControl1.xaml.cs 看起来像这样:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;

namespace WpfApplication1
{


    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class UserControl1 : UserControl
    {
        private string value;
        public string Value
        {
            get { return value; }
            set
            {
                this.value = value;
                textBox1.Text = value;
                Trace.TraceInformation("value set in UserControl1");
            }
        }
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(string), typeof(UserControl1));
        public UserControl1()
        {
            InitializeComponent();
        }
    }
}

我正在使用这样的 UserControl:

<my:UserControl1 x:Name="userControl11" Value="{Binding Path=Name}" />

withDataContext设置为具有 Name 属性并为此属性实现 INotifyPropertyChanged 的​​对象。

4

3 回答 3

2

您将 TextBox 的 Text 和 UserControl 的 Value 之间的连接放在了错误的位置。使用 CLR 属性是为了方便,但绑定引擎不使用它。您需要在 XAML 或后面的代码上显式地将 TextBox 的 Text 绑定到 Usercontrol 的 Value,例如(假设您给用户控件一个名为 root 的名称):

<TextBox x:Name="textBox1" Text="{Binding Path=Value, ElementName=root}"/>
于 2013-08-01T13:47:01.923 回答
2

您不能将其他逻辑或代码添加到包装依赖属性的属性的getset访问器。它不会被执行。

这样做的原因是因为 WPF 设计器实际上会生成代码以直接使用 DependencyProperty。如果您在代码中使用它,get/set 属性只是为了方便。因为您希望 DependencyProperty 和属性的 get/set 做同样的事情,所以您应该只在 get/set 访问器中调用 GetValue 和 SetValue,同时传入相关的依赖属性。

请参阅这些教程:

依赖属性 依赖属性概述

于 2013-08-01T13:52:55.280 回答
2

看看这个实现。它使用非常简单的 MVVM 设计来获得数据绑定。基本上这就是它正在做的事情:

  • 您拥有将其 DataContext 设置为相应 ViewModel 的 UserControl(视图)。
  • 然后将视图上的 TextBox 绑定到该 ViewModel 中的公共属性
  • 通过实现 INotifyPropertyChanged,您可以让 ViewModel 在任何时候更改 Text 属性的值时有效地更新 UI。

这可以针对任意数量的绑定重复并应用于许多不同的类型,例如列表、ObservableCollections、整数。

看法

<UserControl x:Class="WpfApplication1.UserControl1"
         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" d:DesignHeight="48" d:DesignWidth="200">
<Grid>
    <WrapPanel Height="48" HorizontalAlignment="Left" Name="wrapPanel1" VerticalAlignment="Top" Width="200">
        <Label Content="Label" Height="48" Name="label1" Width="100" />
        <TextBox Height="48" Name="textBox1" Width="100" Text={Binding Text} />
    </WrapPanel>
</Grid>

查看代码隐藏

namespace WpfApplication1
{
    using System.Windows;
    using System.Windows.Controls;

    public partial class UserControl1: UserControl
    {
        public UserControl1()
        {
            DataContext = new UserControl1ViewModel();
            InitializeComponent();
        }
    }
}

视图模型

namespace WpfApplication1
{
    using System.Collections.ObjectModel;
    using System.Windows.Controls;

    class UserControl1ViewModel : INotifyPropertyChanged
    {
        // Ultimately, this field (text) would be moved to a model along with 
        // any other data fields for this view but for the sake of space, 
        // I've put it in the ViewModel.
        private string text = "";
        public string Text 
        { 
            get { return text; } 
            set 
            { 
                text = value;
                RaisePropertyChanged("Text");
            } 
        }

        public MainWindowViewModel()
        {
            Text = "Hello!";
        }

        // This is the implementation of INotifyPropertyChanged that is used 
        // to inform the UI of changes.
        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

祝你好运!

于 2013-08-01T14:46:43.143 回答