【问题标题】:Updating control property breaks OneWay binding?更新控件属性会破坏 OneWay 绑定?
【发布时间】:2019-01-22 01:28:27
【问题描述】:

考虑这个非常简单的例子,我有一个这样的 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>

代码背后:

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

所以控件只显示一个文本块,并且每 5 秒递增一次计数器。然后我当然有一个消费者:

主窗口 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>

最后是后面的主要代码:

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

是的,所以 main 后面的代码中有一个计数器,每秒更新一个属性。 XAML 有 2 个 UserControl 实例。一种具有 OneWay 绑定,另一种具有 TwoWay 绑定。

我在这里看到的是,当“SomeControl.cs”中的计数器更新时,第一个 UserControl (OneWay) 的绑定被破坏。有 TwoWay 的会不断更新。

这是设计使然(为什么)?更重要的是,如果我需要更新我的 UserControls 中的属性,我将如何在我的示例中执行此操作 - 以支持 OneWay 绑定?请注意,我真的对本示例中的 TwoWay 绑定不感兴趣,因为它会更新“MySource”,而这不是我想要的!

谢谢。

【问题讨论】:

  • 你试过OneWayToSource吗?
  • 还有;有关更多信息,请参阅此:stackoverflow.com/questions/2305179/…
  • 谢谢@Stefan,是的,我试过了。但这似乎是设计使然。使用答案中提到的 SetCurrentValue 方法似乎可以解决所有问题。

标签: c# wpf binding user-controls dependency-properties


【解决方案1】:

这是设计使然。当您将所谓的local value 分配给依赖项属性时,先前分配的 OneWay 绑定将被替换。 TwoWay Binding 保持活动状态并更新其源属性。

但是有一个解决方法。不要设置本地值,而是设置“当前值”。替换

timer.Tick += (s, e) => Counter = Counter + 1;

timer.Tick += (s, e) => SetCurrentValue(CounterProperty, Counter + 1);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 2020-01-16
    • 2023-03-28
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    相关资源
    最近更新 更多