同步用户控件中多个属性的绑定

发布于 2024-09-06 00:37:45 字数 809 浏览 12 评论 0原文

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

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

欢迎任何建议:)

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

I have an ugly race condition with a WPF usercontrol, which is some kind of extended ComboBox:
The UserControl mainly defines two bindable DependencyProperties, one is the selected item, another one is a list, from which the selected item can be chosen.
Both are bindable, so the control may be initialized with or without a selected item and both properties can be changed via binding (on DataContext change), further the selection may change due to user interaction.
The UserControl contains a ComboBox, whose ItemsSource and SelectedItem are synchronized with my list-property and SelectedItem of the UserControl - so far so good.
The trouble now is, that if both properties are changed (quasi simultaneously) from outside when setting a new DataContext with both values set, it occasionally happens that the SelectedItem is set correctly but the list update causes the selection to be reset to null overwriting the previously set value -> corrupting my DataContext.

To make it short: I need to find a way to "lock" my SelectedItem during list update - but just observing the PropertyChanged-Events is not enough, since I receive them AFTER the updates, where the state to remember is already lost. Further I cannot identify, if the selection change was caused by the user or by (correctly) the binding or (not desired) indirectly by the other binding...
I think I would need some BeforePropertyChanged or OnPropertyChanging event for my DependencyProperties - or another way to manage the ordering of simultanous updates of both properties.

Any suggestions welcome :)

Note that I talk of a list to select an item from, but actually it is some more complex structure that allows quick sorting and filtering, that is also the reason why I do not use an ItemsControl here, but I don't feel like that's relevant for the question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

睫毛溺水了 2024-09-13 00:37:45

这可能对这种情况没有帮助,并且可能不是执行此操作的正确方法,但是您提到了依赖项属性的 OnPropertyChanging 事件。

碰巧的是,当您创建依赖项属性时,您可以在 PropertyMetadata 中指定一个回调,该回调在属性更改时触发,该回调的 EventArgument

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

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

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

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

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

        var box = ((TextBox)sender);

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


    }

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

u_u

This may not help the situation, and is probably not the right way to do this, however you spoke of an OnPropertyChanging event for your dependency properties.

It just so happens that when you create dependency properties you can specify a callback in the PropertyMetadata that fires when the property changes, which has both the old and the new values in its EventArgument.

Here is an example of a Text property with a callback

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

The last parameter is the one you are looking for. The first parameter of the PropertyMetadata constructor is a default value for the property. The second one is where you register a propertychanged callback that happens when the property changes.

in this callback you can handle the bindings to make sure that you don't overwrite your datacontext's SelectedItem.

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

        var box = ((TextBox)sender);

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


    }

To be honest I'm not sure how this helps you with your situation, as I would still not know how to check whether the null value is valid or not. (what I might do is not allow null values if there is an ItemsSource unless the itemssource is just changing [and I might use some kind of flag in the ItemsSource changed callback that gets reset once the selecteditem is changed]). I'm not very clued up on async, but you could perhaps put some sort of lock in here.

u_u

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文