如何正确设置绑定的WPF UserControl

本文关键字:WPF UserControl 绑定 何正确 设置 | 更新日期: 2023-09-27 18:25:52

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

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

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

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

如何正确设置绑定的WPF UserControl

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

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

对于包装依赖属性的属性,不能向getset访问器添加额外的逻辑或代码。它不会被执行。

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

请参阅以下教程:

依赖项属性依赖属性概述

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

  • 您有一个UserControl(视图),它将它的DataContext设置为相应的ViewModel
  • 然后,视图上的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();
        }
    }
}

ViewModel

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));
        }
    }
}

祝你好运!