gpt4 book ai didi

c# - 如何在焦点输入控件上抑制 NotifyPropertyChanged 事件?

转载 作者:行者123 更新时间:2023-11-30 16:48:09 24 4
gpt4 key购买 nike

我的应用程序具有定期数据库同步功能。每当发生同步时,所有输入控件的值都会重置为数据库中的当前值。

但是,当在 TextBox 中键入长文本时发生同步事件时,这非常不方便。

期望的行为是输入控件的值不设置为绑定(bind)属性的值,以防控件当前具有焦点。一旦失去键盘焦点,当前值就应该同步回绑定(bind)的属性,从而同步到数据库(这将是默认行为)。

我的第一个想法是修改我的控件,以便在输入具有键盘焦点时绑定(bind)模式自动设置为 OneWayToSource。目前我没有看到其他选择,只能派生我在我的应用程序中拥有的各种输入控件,这将需要大量工作。

你有没有看到一种在中央位置实现这种行为的方法,以便它被所有 UI 控件使用,最好不要子类化 TextBoxComboBox 等.?

最佳答案

您可以创建一个帮助器来跟踪 IsKeyboardFocusWithin 属性并仅在目标值不包含键盘焦点时更新目标值。例如,您有每秒更改的特定源:

    public partial class MainWindow {
public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
"Data", typeof(string), typeof(MainWindow), new PropertyMetadata(default(string), OnDataChanged));

static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
Debug.WriteLine((string)e.NewValue);
}

public string Data {
get { return (string)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public MainWindow() {
InitializeComponent();
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = TimeSpan.FromMilliseconds(1000);
dt.Tick += Dt_Tick;
dt.Start();
}

void Dt_Tick(object sender, EventArgs e) {
Data = new Random().Next(0, 100).ToString();
}
}

在本例中,这是数据属性。现在, helper 。我决定将其创建为 MarkupExtension 以简化 XAML:

 public class SynchronizationHelperExtension : MarkupExtension {
public Binding Binding { get; set; }
class Helper {
static int index = 0;
bool locked = false;
public static readonly DependencyProperty HelperProperty = DependencyProperty.RegisterAttached(
"Helper", typeof(Helper), typeof(Helper), new PropertyMetadata(default(Helper)));

public static void SetHelper(DependencyObject element, Helper value) {
element.SetValue(HelperProperty, value);
}

public static Helper GetHelper(DependencyObject element) {
return (Helper)element.GetValue(HelperProperty);
}
public static readonly DependencyProperty FocusProperty = DependencyProperty.RegisterAttached("FocusProperty", typeof(bool), typeof(Helper), new PropertyMetadata(false, (o, args) => GetHelper(o)?.OnFocusPropertyChanged(o, (bool)args.OldValue, (bool)args.NewValue)));
public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached("SourceProperty", typeof(object), typeof(Helper), new PropertyMetadata(false, (o, args) => GetHelper(o)?.OnSourcePropertyChanged(o, args.OldValue, args.NewValue)));
public static readonly DependencyProperty TargetProperty = DependencyProperty.RegisterAttached("TargetProperty", typeof(object), typeof(Helper), new PropertyMetadata(false, (o, args) => GetHelper(o)?.OnTargetPropertyChanged(o, args.OldValue, args.NewValue)));

void OnTargetPropertyChanged(DependencyObject o, object oldValue, object newValue) {
o.SetValue(SourceProperty, newValue);
}
void OnSourcePropertyChanged(DependencyObject o, object oldValue, object newValue) {
if (locked)
return;
o.SetValue(TargetProperty, newValue);
}
void OnFocusPropertyChanged(DependencyObject o, bool oldValue, bool newValue) {
locked = newValue;
}
}

public override object ProvideValue(IServiceProvider serviceProvider) {
var helper = new Helper();
var ipwt = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
var dObj = ipwt.TargetObject as DependencyObject;
BindingOperations.SetBinding(dObj, Helper.FocusProperty, new Binding() {Path = new PropertyPath(FrameworkElement.IsKeyboardFocusWithinProperty), RelativeSource = RelativeSource.Self});
Binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(dObj, Helper.SourceProperty, Binding);
Helper.SetHelper(dObj, helper);
return new Binding() {Path = new PropertyPath(Helper.TargetProperty), Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.LostFocus, RelativeSource = RelativeSource.Self }.ProvideValue(serviceProvider);
}
}

我们有 3 个属性:一个存储来自源的实际值 (Helper.SourceProperty)第二 - 存储目标值 (Helper.TargetProperty)第三个用于锁定这些属性之间的同步 (Helper.FocusProperty)我们还有 Binding 属性 - 这是用于将 Target 属性与源绑定(bind)的绑定(bind)(例如 TextBox.TextMainWindow.Data)在 ProvideValue 方法中,我们:

  1. FrameworkElement.IsKeyboardFocusWithinPropertyHelper.FocusProperty 绑定(bind)以锁定更新
  2. 更新原始绑定(bind)使其成为 TwoWay(更改后更新 Data 属性)
  3. 将 BindingExpression 返回给 Helper.TargetProperty

XAML 将如下所示:

<StackPanel>
<TextBox Text="{local:SynchronizationHelper Binding={Binding Data, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}}"/>
<TextBox Text="{local:SynchronizationHelper Binding={Binding Data, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}}"/>
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=Data}"></TextBlock>
</StackPanel>

And the short video demonstrating the result

关于c# - 如何在焦点输入控件上抑制 NotifyPropertyChanged 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38521672/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com