[英]How to suppress a NotifyPropertyChanged event on a focused Input Control?
我的應用程序具有定期數據庫同步。 每當發生同步時,所有輸入控件的值都將重置為數據庫中的當前值。
但是,當在TextBox
鍵入長文本時發生同步事件時,這不僅不方便。
期望的行為是,如果控件當前具有焦點,則輸入控件的值不會設置為bound屬性的值。 一旦鍵盤焦點丟失,當前值應該同步回綁定屬性,從而同步到數據庫(這將是默認行為)。
我的第一個想法是修改我的控件,以便在輸入具有鍵盤焦點時自動將綁定模式設置為OneWayToSource
。 目前我沒有看到另一種選擇,只是為了得到我在我的應用程序中的各種輸入控件,這將是很多工作。
您是否看到了在中心位置實現此類行為的方法,以便所有UI控件都使用它,最好不要對TextBox
, ComboBox
等進行子類化?
您可以創建一個幫助程序來跟蹤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();
}
}
在這種情況下,這是Data屬性。 現在,幫手。 我決定將其創建為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屬性與源綁定的綁定(例如TextBox.Text
與MainWindow.Data
)在ProvideValue方法中,我們:
Helper.FocusProperty
綁定FrameworkElement.IsKeyboardFocusWithinProperty
以鎖定updets Data
屬性) 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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.