【问题标题】:Synchronize Bindings of multiple Properties in a UserControl同步用户控件中多个属性的绑定
【发布时间】:2010-06-11 16:01:54
【问题描述】:

我的 WPF 用户控件有一个丑陋的竞争条件,它是某种扩展的 ComboBox: UserControl主要定义了两个可绑定的DependencyProperties,一个是选中项,另一个是列表,可以从中选择选中项。 两者都是可绑定的,因此可以使用或不使用选定项来初始化控件,并且可以通过绑定更改两个属性(在 DataContext 更改时),进一步的选择可能会由于用户交互而更改。 UserControl 包含一个 ComboBox,其 ItemsSource 和 SelectedItem 与我的列表属性和 UserControl 的 SelectedItem 同步 - 到目前为止一切顺利。 现在的问题是,如果在设置具有两个值的新 DataContext 时从外部更改两个属性(准同时),则偶尔会发生 SelectedItem 设置正确但列表更新导致选择被重置为 null 覆盖以前设置的值 -> 破坏了我的 DataContext。

简而言之:我需要找到一种在列表更新期间“锁定”我的 SelectedItem 的方法 - 但仅观察 PropertyChanged-Events 是不够的,因为我在更新后收到它们,而要记住的状态已经存在丢失。此外,我无法确定选择更改是由用户还是由(正确)绑定或(不希望)间接由其他绑定引起的...... 我认为我的 DependencyProperties 需要一些 BeforePropertyChanged 或 OnPropertyChanging 事件 - 或另一种方式来管理两个属性同时更新的顺序。

欢迎任何建议:)

请注意,我说的是从列表中选择项目,但实际上它是一些更复杂的结构,允许快速排序和过滤,这也是我在这里不使用 ItemsControl 的原因,但我不感觉这与问题相关。

【问题讨论】:

  • 你解决了吗?我目前正在研究一个类似的问题..
  • 如您所见,还没有回应。我已经做的是,确保始终以正确的顺序(在 XAML 中)使用绑定,首先是 ItemsSource,然后是 SelectedItem。但这似乎不够健壮,尤其是如果您重用控件来更改 DataContexts。
  • 一个补充:我已经为我的项目源绑定试验了“IsAsync”。现在我再次将它们全部设置为 IsAsync=False,这似乎保证了 my 案例的正确顺序。不过,我认为了解其他同步技术会很有趣,因为可能存在更复杂的场景,您仍然需要它们。

标签: wpf synchronization wpf-controls dependency-properties race-condition


【解决方案1】:

这可能无济于事,并且可能不是正确的方法,但是您谈到了依赖属性的OnPropertyChanging 事件。

碰巧的是,当您创建依赖属性时,您可以在PropertyMetadata 中指定一个回调,该回调会在属性更改时触发,其EventArgument 中既有旧值也有新值。

这是一个带有回调的 Text 属性示例

public static DependencyProperty TextProperty = DependencyProperty.Register
                                                ("Text", typeof(string), 
                                                 typeof(DecimalTextBox), 
                                                 new PropertyMetadata("", OnTextPropertyChanged));

最后一个参数是您要查找的参数。 PropertyMetadata 构造函数的第一个参数是属性的默认值。第二个是您注册属性更改时发生的属性更改回调。

在此回调中,您可以处理绑定以确保不会覆盖数据上下文的 SelectedItem。

private static void OnTextPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {

        var box = ((TextBox)sender);

        if (((string)e.NewValue)==badvalue)
                box.Text= e.OldValue);


    }

说实话,我不确定这对您的情况有何帮助,因为我仍然不知道如何检查 null 值是否有效。 (如果有 ItemsSource,我可能会做的不是允许空值,除非 itemssource 正在更改[并且我可能会在 ItemsSource 更改的回调中使用某种标志,一旦选定的项目更改就会重置])。我对异步不是很了解,但您也许可以在这里设置某种锁定。

u_u

【讨论】:

  • 同时,我以不同的方式解决了它,但使用 coercevaluecallback 可能对我有所帮助并符合我的要求,因此它回答了我的问题。谢谢。
  • 您是如何以不同的方式解决它的?请添加您使用的答案,而不是将此标记为正确的答案。
猜你喜欢
  • 1970-01-01
  • 2010-12-07
  • 1970-01-01
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 2013-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多