【问题标题】:Binding a property with another property owned to a user control将属性与用户控件拥有的另一个属性绑定
【发布时间】:2015-07-31 13:43:29
【问题描述】:

我想实现几个属性之间的绑定。有可能吗?

我有一个名为“MainWindow”的主窗口类,它拥有一个属性“InputText”。此类包含一个名为 MyUserControl 的用户控件。 MyUserControl 有一个文本框绑定到依赖属性“MyTextProperty”

我想将我的主窗口的属性“InputText”与我的用户控件的依赖属性“MyTextProperty”绑定。所以,如果用户写了一个文本,我希望属性“InputText”、“MyTextProperty”、“MyText”被更新。

用户控制代码:

using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MyUserControl.xaml
    /// </summary>
    public partial class MyUserControl : UserControl
    {

        public string MyText
        {
            get { return (string)GetValue(MyTextProperty); }
            set { SetValue(MyTextProperty, value); }
        }

        public static readonly DependencyProperty MyTextProperty =
            DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new PropertyMetadata(0));



        public MyUserControl()
        {
            this.DataContext = this;
            InitializeComponent();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string property)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
            }
        }

    }
}

WPF 用户控制代码:

<UserControl x:Class="WpfApplication1.MyUserControl"
             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="25 " d:DesignWidth="100"
             Background="Black">
    <Grid>
        <TextBox Height="20" Width="100" Text="{Binding MyText}"></TextBox>
    </Grid>
</UserControl>

主窗口代码:

using System;
using System.Linq;
using System.Windows;
using System.ComponentModel;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private string inputText;

        public string InputText
        {
            get { return inputText; }
            set 
            { 
                inputText = value;
                NotifyPropertyChanged("InputText");
            }
        }

        public MainWindow()
        {
            this.DataContext = this;

            InitializeComponent();

        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(String property)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
            }
        }
    }
}

WPF主窗口代码:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:myNS="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="80" Width="300">
    <Grid>
        <StackPanel Orientation="Vertical">
            <myNS:MyUserControl x:Name="test" MyText="{Binding InputText}"></myNS:MyUserControl>
            <Button Name="cmdValidation" Content="Validation" Height="20"></Button>
        </StackPanel>
    </Grid>
</Window>

谢谢!

【问题讨论】:

  • 上面的代码有错误吗?您在尝试绑定这些属性时遇到了什么确切的问题。
  • 你的UserControl应该继承MainWindow的DataContext,那么为什么不直接将TextBox的Text属性绑定到InputText属性呢?

标签: c# wpf binding


【解决方案1】:

如果您希望您发布的代码以尽可能少的更改工作,那么:

在 MainWindow.xaml 中,更改

MyText="{Binding InputText}"

到

MyText="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.InputText, Mode=TwoWay}"

如果你想让 UC 更新 InputText,你需要 TwoWay。

此外,在 MyUserControl.xaml.cs 中,在 DependencyProperty.Register 语句中,您将字符串的 PropertyMetadata 默认值设置为 0 - 将其更改为适合字符串的值 - 例如 null 或 string.empty。

public static readonly DependencyProperty MyTextProperty =
    DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new PropertyMetadata(null));

如果你想稍微修改一下代码,你可以在用户控件中让它更复杂,但在使用时更简单:

使依赖属性 MyText 默认绑定两种方式

停止在用户控件中设置 DataContext

更改 UC xaml 文本绑定以使用 UC 的相对源

我总是觉得代码更容易理解,所以这里是您的文件的修改版本: MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:myNS="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="180" Width="300">
    <Grid>
        <StackPanel Orientation="Vertical">
            <TextBlock>
                <Run Text="MainWindow.InputText: " />
                <Run Text="{Binding InputText}" />
            </TextBlock>
            <TextBlock>
                <Run Text="MyUserControl.MyText: " />
                <Run Text="{Binding ElementName=test, Path=MyText}" />
            </TextBlock>
            <myNS:MyUserControl x:Name="test" MyText="{Binding InputText}"></myNS:MyUserControl>
            <Button Name="cmdValidation" Content="Validation" Height="20"></Button>
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Windows;
using System.ComponentModel;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private string inputText = "Initial Value";

        public string InputText
        {
            get { return inputText; }
            set
            {
                inputText = value;
                NotifyPropertyChanged("InputText");
            }
        }

        public MainWindow()
        {
            this.DataContext = this;

            InitializeComponent();

        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(String property)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
            }
        }
    }
}

MyUserControl.xaml

<UserControl x:Class="WpfApplication1.MyUserControl"
             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="25 " d:DesignWidth="100"
             Background="Black">
    <Grid>
        <TextBox Height="20" Width="100" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=MyText, UpdateSourceTrigger=PropertyChanged}"></TextBox>
    </Grid>
</UserControl>

MyUserControl.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MyUserControl.xaml
    /// </summary>
    public partial class MyUserControl : UserControl
    {

        public string MyText
        {
            get { return (string)GetValue(MyTextProperty); }
            set { SetValue(MyTextProperty, value); }
        }

        public static readonly DependencyProperty MyTextProperty =
            DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new FrameworkPropertyMetadata(null) { BindsTwoWayByDefault = true });

        public MyUserControl()
        {
            InitializeComponent();
        }
    }
}

【讨论】:

    【解决方案2】:

    首先,

    this.DataContext = this;
    

    没有。就是不行。您正在覆盖由其父窗口设置的UserControl 中的DataContext。

    对于你的UserControl,给它一个x:Name,并直接绑定到依赖属性。

    <UserControl
        ...
        x:Name="usr">
    
        <TextBox Text="{Binding MyText, ElementName=usr}" ... />
    

    完成后,您可以简单地将您的MyText 属性绑定到MainWindow 的DataContext。

    <myNS:MyUserControl x:Name="test" MyText="{Binding InputText}" />
    

    【讨论】:

      猜你喜欢
      • 2013-04-20
      • 2015-06-29
      • 1970-01-01
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-15
      • 2010-11-14
      相关资源
      最近更新 更多