如何正确设置WPF UserControl进行绑定

时间:2013-08-01 13:41:42

标签: c# wpf binding

我想创建一个UserControl,它本质上是一个带有TextBox的Label。现在我希望能够将TextBox.Text绑定到不同的值。

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

我的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}" />

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

3 个答案:

答案 0 :(得分:2)

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

<TextBox x:Name="textBox1" Text="{Binding Path=Value, ElementName=root}"/>

答案 1 :(得分:2)

您无法为包装依赖项属性的属性的获取设置访问者添加其他逻辑或代码。它不会被执行。

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

请参阅以下教程:

Dependency Properties Dependency Properties Overview

答案 2 :(得分:2)

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

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

这可以针对任意数量的绑定重复,并应用于许多不同类型,例如Lists,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));
        }
    }
}
祝你好运!