c# – 具有绑定模式的WPF UserControl = OneWay

c# – 具有绑定模式的WPF UserControl = OneWay,第1张

概述我正在尝试使用可绑定属性制作一个示例 WPF用户控件(可能更好地说“开发人员控件”).我的代码包含以下文件: ----- MainWindow.xaml -----<Window x:Class="Test_Binding.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 我正在尝试使用可绑定属性制作一个示例 WPF用户控件(可能更好地说“开发人员控件”).我的代码包含以下文件:

----- MainWindow.xaml -----<Window x:Class="Test_Binding.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:testBinding="clr-namespace:Test_Binding"        title="MainWindow" Height="350" WIDth="525">    <StackPanel>        <testBinding:MyLabelledTextBox x:name="MLTB" LabelText="My custom control: MyLabelledTextBox" Text="{Binding StringData,Mode=OneWay}" />    </StackPanel></Window>----- MainWindow.xaml.cs -----using System.windows;namespace Test_Binding{    /// <summary>    /// Interaction logic for MainWindow.xaml    /// </summary>    public partial class MainWindow : Window    {        public MainWindow()        {            this.DataContext = new MyDataObject();            this.InitializeComponent();        }    }}----- MyDataObject.cs -----using System.Runtime.CompilerServices; // CallerMembernameusing System.ComponentModel; // INotifyPropertyChangednamespace Test_Binding{    public class MyDataObject : INotifyPropertyChanged    {        public event PropertyChangedEventHandler PropertyChanged;        private string stringData;        public string StringData        {            get { return this.stringData; }            set            {                if (value != this.stringData)                {                    this.stringData = value;                    this.OnPropertyChanged();                }            }        }        private voID OnPropertyChanged([CallerMembername] string propertyname = null)        {            if (this.PropertyChanged != null)            {                this.PropertyChanged(this,new PropertyChangedEventArgs(propertyname));            }        }        public MyDataObject()        {            System.Timers.Timer t = new System.Timers.Timer();            t.Interval = 10000;            t.Elapsed += t_Elapsed;            t.Start();        }        private voID t_Elapsed(object sender,System.Timers.ElapsedEventArgs e)        {            this.StringData = ((this.StringData ?? string.Empty).Length >= 4 ? string.Empty : this.StringData + "*");        }    }}----- MyLabelledTextBox.xaml -----<UserControl x:Class="Test_Binding.MyLabelledTextBox"             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="300" d:DesignWIDth="300">  <StackPanel Background="Yellow">    <GrID>        <GrID.RowDeFinitions>            <RowDeFinition Height="auto" />        </GrID.RowDeFinitions>        <GrID.ColumnDeFinitions>            <ColumnDeFinition WIDth="0.5*" />            <ColumnDeFinition WIDth="0.5*" />        </GrID.ColumnDeFinitions>           <Label x:name="MLTBLabel" GrID.Row="0" GrID.Column="0" />        <TextBox x:name="MLTBTextBox" GrID.Row="0" GrID.Column="1" Background="Yellow" Text="{Binding Text,Mode=TwoWay}" />    </GrID>  </StackPanel></UserControl>----- MyLabelledTextBox.xaml.cs -----using System.windows;using System.windows.Controls;namespace Test_Binding{    /// <summary>    /// Interaction logic for MyLabelledTextBox.xaml    /// </summary>    public partial class MyLabelledTextBox : UserControl    {        public static Readonly DependencyProperty LabelTextProperty =            DependencyProperty.Register("LabelText",typeof(string),typeof(MyLabelledTextBox),new PropertyMetadata(string.Empty,MyLabelledTextBox.LabelTextPropertyChanged));        public string LabelText        {            get { return (string)this.GetValue(MyLabelledTextBox.LabelTextProperty); }            set { this.SetValue(MyLabelledTextBox.LabelTextProperty,value); }        }        public static Readonly DependencyProperty TextProperty =            DependencyProperty.Register("Text",MyLabelledTextBox.TextPropertyChanged));        public string Text        {            get { return (string)this.GetValue(MyLabelledTextBox.TextProperty); }            set { this.SetValue(MyLabelledTextBox.TextProperty,value); }        }        public MyLabelledTextBox()        {            this.InitializeComponent();            this.MLTBLabel.DataContext = this;            this.MLTBTextBox.DataContext = this;            this.MLTBTextBox.TextChanged += new TextChangedEventHandler(this.MLTBTextBox_TextChanged);        }        private voID MLTBTextBox_TextChanged(object sender,TextChangedEventArgs e)        {            this.Text = this.MLTBTextBox.Text; // transfer changes from TextBox to bindable property (bindable property change notification will be fired)        }        private static voID LabelTextPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)        {            ((MyLabelledTextBox)d).MLTBLabel.Content = (string)e.NewValue; // transfer changes from bindable property to Label        }        private static voID TextPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)        {            ((MyLabelledTextBox)d).MLTBTextBox.Text = (string)e.NewValue; // transfer changes from bindable property to TextBox        }    }}

有一个“MyDataObject”类的实例,其属性为“StringData”,使用计时器定期修改.我的用户控件绑定到其属性“StringData”.如果“MainWindow.xaml”文件中的绑定设置为“TwoWay”,则用户控件会不断更新,但如果我使用“OneWay”绑定,则用户控件会更新一次,然后“PropertyChanged” “MyDataObject”类实例的事件不会再次触发,因为它突然没有订阅者.

为什么“OneWay”绑定在被调用一次后停止工作?
什么代码更改将允许“TwoWay”和“OneWay”绑定继续工作?

解决方法 首先.

this.MLTBLabel.DataContext = this;this.MLTBTextBox.DataContext = this;

Noooooooooooooooo!

决不.永远.永远.从代码隐藏中设置DataContext.一旦执行此 *** 作,您就会失去从父控件绑定到用户控件的依赖项属性的神奇美感.换句话说,就是不要这样做.

这是你应该做的:

为UserControl提供x:名称.

<UserControl ...    x:name="usr">

将UserControl的依赖属性绑定到元素,如下所示:

<TextBlock Text="{Binding MyDependencyProperty,Elementname=usr}" ... />

将UserControl的DataContext属性绑定到元素,如下所示:

<TextBlock Text="{Binding MyDataContextProperty}"/>

使用此方法将允许您在MainWindow中设置UserControl的DataContext,但仍然能够绑定到UserControl中UserControl的依赖项属性.如果在代码隐藏中设置UserControl的DataContext,则无法绑定到依赖项属性.

现在,解决你的实际问题.

所有这些:

private voID MLTBTextBox_TextChanged(object sender,TextChangedEventArgs e)    {        this.Text = this.MLTBTextBox.Text; // transfer changes from TextBox to bindable property (bindable property change notification will be fired)    }    private static voID LabelTextPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)    {        ((MyLabelledTextBox)d).MLTBLabel.Content = (string)e.NewValue; // transfer changes from bindable property to Label    }    private static voID TextPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)    {        ((MyLabelledTextBox)d).MLTBTextBox.Text = (string)e.NewValue; // transfer changes from bindable property to TextBox    }

忘掉它.看起来你正试图解决我之前谈到的错误行为.

您应该绑定到您的依赖项属性:

<Label GrID.Row="0" GrID.Column="0" Text="{Binding Text,Elementname=usr}"/>

您遇到的另一个问题是,在您的MainWindow中,您正在使用UserControl上的绑定.

Text="{Binding StringData,Mode=OneWay}"

现在,因为您已经在代码隐藏中设置了DataContext.这有效地说的是:

从当前控件的DataContext绑定到StringData.

在您的情况下,与您的MainWindow DataContext完全不同. (因为您在UserControl中明确设置了DataContext).

贯穿我之前提到的.有很多东西需要学习,但这是一个开始.

总结

以上是内存溢出为你收集整理的c# – 具有绑定模式的WPF UserControl = OneWay全部内容,希望文章能够帮你解决c# – 具有绑定模式的WPF UserControl = OneWay所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1231347.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存