您可以创建一个帮助程序,该帮助程序将跟踪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();
}
}
在这种情况下,这是数据属性。现在,帮手。我决定将其创建为一个的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属性之间的同步 - 这是绑定你用你的目标属性与来源(例如TextBox.Text
与MainWindow.Data
) 在ProvideValue方法结合我们:
- 结合
FrameworkElement.IsKeyboardFocusWithinProperty
与Helper.FocusProperty
锁定updets
- 更新原始的结合,使其双向(更新变更后的
Data
属性)
- 返回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
目前还不清楚,期望的行为是什么。你想跳过集中控制还是想跳过绑定属性的更新?如果它的值被改变了?下一个同步阶段应该发生什么情况,使用滑动的值? – Dennis
我添加了一段来指定所需的行为=) – Andre
这是一个有趣的问题。当用户正在编辑并且您需要更新该字段时,您会做什么?用户总是赢吗?这听起来像你需要一个自定义的绑定实现,监听用户输入并阻止来自源的更新... – Will