开发者

Binding failures when adding another property

I have a main view that binds to subviews like this (the backing property is of type object):

<ContentControl Content="{Binding WalletsView}"/>

Now, I've added another property to the corresponding viewmodel, namely

public SmartObservableCollection<Selectable<Type>> PriceGrabbers {get; private set;}

where SmartObservableCollection is derived from ObservableCollection to make multithreaded updates easier.

Now I get a lot of binding errors (in fact, all bindings in the sub viewmodels run through the debug window) like this开发者_开发百科 (interestingly, if I remove the PriceGrabbers property again, all errors disappear):

System.Windows.Data Error: 40 : BindingExpression path error: 'OverviewHidden' property not found on 'object' ''MainWindowViewModel' (HashCode=30986197)'. BindingExpression:Path=OverviewHidden; DataItem='MainWindowViewModel' (HashCode=30986197); target element is 'ColumnDefinition' (HashCode=22768693); target property is 'NoTarget' (type 'Object')

So the binding engine apperently tries to find any and all bindings on the main viewmodel. The bindings work perfectly fine. While this is okay, I'd rather have errors go away. Did anybody of you already encounter this problem, and if yes, how did you solve it?


The problem isn't with WPF but with my usage of MEF as composition container. The property modifies the import order of classes and the ViewModel coresponding to MainWIndow is assigned to all Views first, after which the correct one is assigned. When the data context is refreshed, all bindings are renewed, thus the application works.

edit and now I found the complete reason for it.

SmartObservableCollection takes an Action<Action>> parameter to execute on CollectionChanged events, this is needed due to most of my collections getting updated in a multithreaded manner, but the events have to be executed in the GUI thread, otherwise you will get an exception.

For this, my Views expose Dispatcher.Invoke() and Dispatcher.BeginInvoke() as methods, which I then supply to the collection.

At startup, the DataContexts are assigned in the base class ViewModel by the following lines:

Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate()
{
    view.DataContext = this;
});

Who has an idea already?

The reason for this hickup was the simple fact I supplied the Dispatcher.Invoke() method instead of Dispatcher.BeginInvoke() to the collection. By doing this (and the fact it was used in the MainWindowViewModel), it got executed before any DataContexts got assigned to other ViewModels.

Now, the next step occurs - the WPF engine tries to bind to the data in the sub views. As DataContext is null, the binding engine walks up the visual tree until it finds a set DataContext, in this case the first set DataContext is in MainWindowView, and it is MainWindowViewModel. Now, after the collection finished, all other actions get called and the DataContexts are assigned appropiately, thus reexecuting the binding engine which finds a non-null DataContext on the sub views and binds correctly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜