在UserControl中同步多个属性的绑定

3
我有一个WPF用户控件的丑陋竞态条件问题,它是某种扩展ComboBox: 该UserControl主要定义了两个可绑定的DependencyProperties,一个是选定的项目,另一个是列表,可以从中选择选定的项目。两者均可绑定,因此控件可以使用或不使用选定的项目进行初始化,并且两个属性都可以通过绑定(在DataContext更改时)进行更改,进一步,由于用户交互,选择可能会发生更改。 UserControl包含一个ComboBox,其ItemsSource和SelectedItem与我的列表属性和UserControl的SelectedItem同步-到目前为止还好。现在的问题是,如果同时从外部更改这两个属性(几乎同时),当设置具有两个值的新DataContext时,偶尔会发生SelectedItem被正确设置但列表更新导致选择被重置为null,覆盖先前设置的值->破坏我的DataContext。
简而言之:我需要找到一种方法来在列表更新期间“锁定”我的SelectedItem-但仅观察PropertyChanged事件是不够的,因为我在更新后接收到它们,在那里记住状态已经丢失。此外,我无法确定选择更改是由用户引起的还是(正确地)由绑定引起的或者(不希望的)间接由其他绑定引起的......我认为我需要一些BeforePropertyChanged或OnPropertyChanging事件来处理我的DependencyProperties-或者另一种管理同时更新两个属性的顺序的方式。 欢迎任何建议 :)
请注意,我谈论的是选择项目的列表,但实际上它是一些更复杂的结构,允许快速排序和过滤,这也是为什么我在这里不使用ItemsControl的原因,但我不认为这与问题相关。

你解决这个问题了吗?我有一个类似的问题,正在调查中。 - Andrew Anderson
目前还没有响应,正如您所见。我已经做的是确保绑定始终按正确顺序使用(在XAML中),首先是ItemsSource,然后是SelectedItem。但这似乎不够健壮,特别是如果您重用控件来更改DataContexts。 - Simon D.
有一个补充:我曾经尝试使用“IsAsync”来处理我的项源绑定。现在我已将它们全部设为IsAsync=False,这似乎可以保证我的情况下的正确顺序。 不过,我认为了解其他同步技术仍然很有意义,因为可能存在更复杂的场景需要它们。 - Simon D.
1个回答

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 可能会对我有所帮助,并且符合我的要求,因此它回答了我的问题。谢谢。 - Simon D.
你是如何以不同的方式解决它的?请添加你使用的答案,而不是将此标记为正确答案。 - Johannes Egger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接