[英]Updating control property breaks OneWay binding?
Consider this very simple example where I have a UserControl like this: 考虑这个非常简单的示例,其中有一个类似UserControl的用户:
UserControl XAML: UserControl XAML:
<UserControl x:Class="BindingTest.SomeControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="SomeControlElement">
<Grid>
<TextBlock Text="{Binding ElementName=SomeControlElement, Path=Counter}" />
</Grid>
</UserControl>
Code Behind: 背后的代码:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
namespace BindingTest
{
public partial class SomeControl : UserControl
{
public SomeControl()
{
InitializeComponent();
var timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 5);
timer.Tick += (s, e) => Counter = Counter + 1;
timer.Start();
}
public int Counter
{
get { return (int)GetValue(CounterProperty); }
set { SetValue(CounterProperty, value); }
}
public static readonly DependencyProperty CounterProperty = DependencyProperty.Register(nameof(Counter), typeof(int), typeof(SomeControl), new PropertyMetadata(0));
}
}
So the Control just shows a TextBlock and every 5 seconds increments the Counter. 因此,控件仅显示一个TextBlock,并且每5秒钟递增一次Counter。 And then I have a consumer of course: 然后,我当然有一个消费者:
MainWindow XAML: MainWindow XAML:
<Window x:Class="BindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BindingTest"
x:Name="MainWindowName" Width="200" Height="300">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel>
<local:SomeControl Counter="{Binding ElementName=MainWindowName, Path=SomeSource, Mode=OneWay}" />
<local:SomeControl Counter="{Binding ElementName=MainWindowName, Path=SomeSource, Mode=TwoWay}" />
</StackPanel>
</Grid>
</Window>
And lastly the Main Code behind: 最后是后面的主要代码:
using System;
using System.Windows;
using System.ComponentModel;
using System.Windows.Threading;
namespace BindingTest
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
var timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 1);
timer.Tick += (s, e) => SomeSource = SomeSource + 1;
timer.Start();
}
private int someSource;
public int SomeSource
{
get => someSource;
set
{
if (someSource != value)
{
someSource = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SomeSource)));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
Right, so the main has a counter in code behind that updates a property every second. 是的,因此主体在代码后面有一个计数器,该计数器每秒更新一次属性。 The XAML has 2 instances of the UserControl. XAML具有2个UserControl实例。 One that has OneWay binding, and one that has TwoWay binding. 一种具有OneWay绑定,另一种具有TwoWay绑定。
What I see here, is that when the Counter in "SomeControl.cs" updates, the binding for the first UserControl (OneWay) is broken. 我在这里看到的是,当“ SomeControl.cs”中的Counter更新时,第一个UserControl(OneWay)的绑定被打破。 The one with TwoWay keeps on updating. 带有TwoWay的版本会不断更新。
Is this by design (and why)? 这是设计使然(为什么)吗? And more importantly, if I have the need for updating properties in my UserControls, how would I do this in my example - in order to support OneWay bindings? 更重要的是,如果我需要更新UserControls中的属性,那么在我的示例中该怎么做-为了支持OneWay绑定? Mind that, I'm really not interested in TwoWay binding in this example because it would update "MySource" which is not what I wanted! 请注意,在此示例中,我对TwoWay绑定真的不感兴趣,因为它将更新“ MySource”,这不是我想要的!
Thanks. 谢谢。
It's by design. 这是设计使然。 When you assign a so-called local value to a dependency property, a previously assigned OneWay Binding is replaced. 当您为依赖项属性分配所谓的本地值时 ,将替换先前分配的OneWay绑定。 A TwoWay Binding remains active and updates its source property. TwoWay绑定保持活动状态并更新其source属性。
There is however a workaround. 但是,有一种解决方法。 Do not set a local value, but a "current value". 不要设置本地值,而要设置“当前值”。 Replace 更换
timer.Tick += (s, e) => Counter = Counter + 1;
with 同
timer.Tick += (s, e) => SetCurrentValue(CounterProperty, Counter + 1);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.