Synchronize Bindings of multiple Properties in a UserControl

故事扮演 提交于 2020-01-02 07:17:13

问题


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.


回答1:


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



来源:https://stackoverflow.com/questions/3024312/synchronize-bindings-of-multiple-properties-in-a-usercontrol

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!