WPF Thread binding access error on binding in MVVM - c#

So I am trying to incorporate dynamic-data-display for WPF into my MVVM caliburn project (I am using the LineChart control from future of dynamic data display, if anyone wishes to test this error). There is a LineChart that binds to an ObservableCollection. It only works if the collection is made in the code-behing of the control which has the LineChart. If you try to bind to a collection the ViewModel the dependency property raises an InvalidOperationException. How can this problem be solved?
I have seen that happen when you change the collection which the property is binded to and know ways to fix that, but never in the actuall proccess of binding. I've tried putting the creation of the collection in a dispatcher invoke (like you wold do with an add or remove) but it didn't help.
Edit: As I stated in the second paragraph the exception is NOT at the point of changing the collection. It is being raised at the point of binding. Even more, I have tried to use the solutions in the other question and they did not help.
Edit #2: The exception message is "The calling thread cannot access this object because a different thread owns it".
People keep telling me solutions to collection changes but it doesn't even get to the changes. It fails at binding stage (ItemsSource="{binding collection}" in xaml).
Edit #3: I double-checked and noticed that the ViewModel is created in the UI thread which only made more questions.

Ok, it took me quite a while to find the root cause of your problem.
Unlike from what others suspected, this isn't a multithreading issue at all.
Instead it's an issue with the DynamicDataDisplay library you are using.
There's a clear reason why your ItemsSource binding works on your ListBox object and doesn't work on Chart (of type Microsoft.Research.DynamicDataDisplay.Markers2.LineChart) :
Chart neither has a visual nor a logical parent.
You can check this if you insert the following code into Button_Click and set a breakpoint after them:
var visualParent = VisualTreeHelper.GetParent(Chart);
var logicalParent1 = Chart.Parent;
var logicalParent2 = LogicalTreeHelper.GetParent(Chart);
You can see that they are all null.
So the Binding that you set on LineChart.ItemsSourceProperty with Path=ExampleCollection cannot find any source value and just assigns null to the ItemsSource. That's because the DataContext is inherited from the parent - but when there isn't any parent then there isn't any DataContext to inherit either.
And because Chart isn't part of the visual or logical tree, there is no (easy) way any binding to an outside DataContext can even work.
To verify that the DataContext is null just add this line to the preceding code:
var dataContext = Chart.DataContext;
Now there are three possible solutions for this.
First, you can manually inherit the DataContext from Window using the following code:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Just add the following line.
Chart.DataContext = DataContext;
Chart.StrokeThickness = 3;
Chart.SetBinding(LineChart.ItemsSourceProperty, new Binding("ExampleCollection"));
// ...
}
If you simply add this one line, you'll see that your other multithreaded code is working just fine and the chart is updated with some kind of sine wave pattern.
Second, as another possible solution you can consult the documentation for the DynamicDataDisplay library and check the correct and intended way to assign an ItemsSource to a LineChart using data binding.
I tried searching for documentation myself and even debugged a lot of code from that library for two hours or so, but the documentation is nearly non-existent and the code is far too complex to fully understand it in a few hours. I tried using several tools (Visual Studio Live Visual Tree, Snoop, ...) for displaying the visual tree of the ChartPlotter but I got a StackOverflowException every time, so essentially something in this library is kind of flawed and buggy.
Third, you can use a Resource as a kind of proxy object to create a "binding bridge" to the same instance of the MainWindowViewModel.
For this to work, you have to do something like suggested here: Data binding outside the visual tree. Data Context bridging
Bottom line: So, if you just want to get the job done, I would set the DataContext in code like shown above. (Especially if the instance of the ViewModel in the DataContext never changes.)
If you want to use pure data binding then I would probably use the "binding bridge" or search for another charting library that supports this scenario.

As THIS thread states you can use the UI dispatcher and invoke the function that changes your ObservableCollection on the UI thread. Application.Current.Dispatcher should give you the UI dispatcher. As the solution suggests it can be right in the ViewModel. However, a cleaner and more generic solution is to IMPLEMENT a concurrent and still observable collection it would still store the dispatcher and run the changes on the UI (or specified) thread.

Related

Why is WPD Datagrid Usercontrol bound to row datacontext not updating?

I have a DataGrid bound via a ListCollectionView to an ObservableCollection of Objects with type Job, say. Each cell in the DataGrid contains a UserControl which has a dependency property named Job which is bound to the DataGridRow.DataContext (using Mode=TwoWay). Everything displays correctly.
The problem is that I have a background process which mutates objects referenced by the Job object and those get displayed by the UserControl. Obviously, Job does not change so the view does not change.
How can I get the user controls in each cell to update themselves with the new data?
With lists there are 3 kinds of ChangeNotification you have to take care of:
the one for each property of the Job Class.
the one if elements are added or removed from the collection. That is the only part ObservableCollection takes care off.
the one on the property exposing the list/CollectionView/whatever. ObservableCollection lacks a AddRange function so on large operations (like a rebuild of the list) it would spam the UI with changes. The solution is to build a new list in the background, then expose it in this property.
One particular issue might be the Background Process too, if it is Multithreading. GUI's are protected against being written from the wrong Thread. But threads are also notoriously good at swallowing Exceptions. Usually you need to write a faulty Catch, but they do it for free. As a result, your might run int oa CrossThread exception and never notice it.
For a better answer, we need some actuall code. Like teh job class, the BackgroundProcess, etc.

x:Bind in UWP (Universal Windows Platform)

Right. So moving from WPF to UWP, I'm trying to use x:Bind to get compile-time benefits. Simple scenarios work fine; however I have found a number of issues that I was not able to solve. They are all related, so I thought I'd post them in one place:
I haven't been able to make Intellisense work with x:Bind. I have set DataContext (as well as d:DataContext just as we do in WPF) both in XAML and in the constructor, but it won't show members no matter what. Has anyone done this successfully?
Then I read somewhere that in UWP, DataContext is always set to Page's code-behind (really??) and that I need to define a ViewModel type property in the code-behind and then use that property in x:Bind. Is this correct? I tried it and it works but gives rise to the next question.
If I define a property of ViewModel type in Page's code-behind, Any sub-properties that raise PropertyChanged notifications do not update the UI. For example, if the code-behind property is named Game (of type GameVM) and there is a public property in GameVM named Player (of type GamePlayer), and in turn GamePlayer contains a property named Name, the x:Bind path will look like {x:Bind Path=Game.Player.Name}. But if I do this, any change notifications raised from within Name property do not update Page's UI.
One alternate I tried was to listen to PropertyChanged at each level and then bubble it up the hierarchy, but that hasn't worked. Even if it does, doing this seems a bit too much work. In WPF sub-properties like Game.Player.Name work properly without having to doing property change bubbling. Or am I missing something?
Right. After playing with it for a few days and searching numerous references, here are my findings:
{x:Bind} lacks design-time support. The feature is on the wishlist though. You may want to upvote it there.
(The new version of Visual Studio 15.4.4 does support Intellisense in {x:Bind}in the required way.)
{x:Bind} uses code-behind as its DataContext. So you need to define a public property of your ViewModel type in the code-behind and then use it in your {x:Bind} path.
As pointed out by IInspectable, the default mode for {x:Bind} is OneTime, unlike {Binding} which uses OneWay or TwoWay in almost all cases. So you need to explicitly specify Mode in your binding. People coming from WPF should take special care of it.
Sub-properties that implement notification change work perfectly fine in {x:Bind}. There is no need of bubbling these notifications upwards in the property hierarchy. The problem I was facing (#3 in the question) was because my sub-property was of type List<T>. I changed it to ObservableCollection<T> and it started working.
Hope this works somebody down the road.
Well as a beginner, the only question I can answer for you is the first one. Intellisense does not work inside the {x:Bind}. The members are never shown there in UWP for some unknown reasons. As for the next two questions of yours, I am still working on them.
I ran into the same challenge that you have seen. In my experience, in order to create the compile-time binding and have it update with custom objects as properties, the Page class seems to need to know about the data context and custom objects... all you need to do is reference them in the code behind, and then bind to them in the XAML. This creates the code generation objects it needs.
For example, I have a viewmodel, CustomerViewModel that is bound in XAML. That viewmodel also has a property of type IGuest. In order to use the guest object and have it update properly, I came up with this in the code behind...
CustomerViewModel vm
{
get
{
return (CustomerViewModel)DataContext;
}
}
IGuest g
{
get
{
return vm.CurrentGuest;
}
}
public CartGuestControl()
{
this.InitializeComponent();
}
You don't need to assign any of the UI data contexts from the code behind... simply reference the datacontext that is bound in XAML. When binding to any straight viewmodel properties, I use {x:Bind Path=vm.IsEditing, Mode=OneWay}. For binding to any of the guest properties, it looks like this, {x:Bind Path=g.FirstName, Mode=TwoWay}. You could do something like this for your Player object.
I have run into times where x:Bind simply won't do what I expect it to do no matter what I try. This can usually be solved by breaking things out into smaller user controls with more specific data contexts or by using "regular" Binding.

XAML: Under the Hood

Well, i must admit, still sometimes XAML seems a bit mysterious to me. The thing is, i always liked to debug through the C# code (setting lots of breakpoints in them) to get the idea of "what is happening" and "how is it happening". But with declarative XAML syntax that's not an option. I think you'll agree that to work with XAML, or to be precise, to work with/understand some existing XAML code you got to "already know" how things work with XAML declaration. There is just no way you can know/learn things investigating the execution of your application code. So i'm more than interested to take a look through XAML inside-out, as detailed as possible. I'm NOT talking about "learning" XAML, I know the basic stuff. May be i can provide some examples to clarify the sort of things i'm looking for -
Compared to C# code how an object gets instantiated when we use them in XMAL? Are they stored in managed heap? Same way as C# code-instantiated objects?
How the properties get set while using Mark-Up Extension syntax for Data/Command Binding?
When any property of an INotifyPropertyChanged type gets updated, how the Binding instatnce inside the XAML syntax updates the itself? How exactly it gets notified it at the first place, & by whom?
A viewmodel can be set as the DataContext of a view at runtime by defining Typed DataTemplate, like -
<DataTemplate DataType="{x:Type viewmodels:AccountsViewModel}">
<views:Accounts/>
</DataTemplate>
How does it happen actually? What are the rules for setting DataContext other than searching for the DataContext property upward the logical tree?
How the whole template things (DataTemplate, ControlTemplate & ItemsPanelTemplate) are treated/resolved at run time.
etc. etc. etc.
So if you are good/experienced/expert in XAML what would you suggest (links, articles, blogposts, books whatever) as reference that helps getting clear & deeper understanding about how XAML works "under-the-hood"? Thanks in advance.
Most can be explained by don't thinking of XAML as a real programming language, more like a declarative language. Everything you do in xaml, can be made in C# aswell, and in fact this is whats happening.
Compared to C# code how an object gets instantiated when we use them
in XMAL? Are they stored in managed heap? Same way as C#
code-instantiated objects?
Yes because they are just c# objects. Most resources are stored in a hibernated state, i rememberd the word inflated somewhere. Converter or other "direct" c# objects are created when they are needed. Important here is that these resources are usually shared, so they will get created only once.
How the properties get set while using Mark-Up Extension syntax for Data/Command Binding?
This again depends on where you use the markup extension. In a Style? In a Template? In a instanced user control like a window? Usually they are evaluated when you actually need them. It wouldn't make sense to evaluate them, when the inflated style is stored in the actual resource dictionary. They get evaluated when you actually use the style on an object.
When any property of an INotifyPropertyChanged type gets updated, how
the Binding instatnce inside the XAML syntax updates the itself? How
exactly it gets notified it at the first place, & by whom?
By the binding engine. WPF checks if your DataContext inherits the INotifyPropertyChanged interface, attaches to the event provided by the interface and listens to any changes. If such an event is raised, the binding engine will just call the getter again.
How does it happen actually? What are the rules for setting DataContext
other than searching for the DataContext property upward
the logical tree?
In short: None other. Datacontext is simply an inherited attached property. If you don't re set it on a child control, it will take the value the parent has until it reached the root. The only exception to this are ContentControls and ContentPresenter they will not inherit the DataContext but will change them depending on the content. So these controls always have by default the Content as their DataContext.
How the whole template things (DataTemplate, ControlTemplate & ItemsPanelTemplate) are treated/resolved at run time.
Simply spoken: Everytime WPF finds a non ui object, it tries to find a DataTemplate for the given type. In an ItemsControl for example: You can bind a list of MyClass; unless you provide an explicit DataTemplate or DataTemplateSelector it will search the resource tree upwards for an implicit style. Again remember that this already does not happen in XAML, but on the C# objects that was generated out of the xaml.
And is it by any means possible (at present or near future) to debug
through XAML code?
How do you think you can debug something that is not executed, but evaluated on compile time?
Please don't take this as 100% correct. Over the Years this is what i gathered of informations about XAML and the usage. If you have any corrections or find something that is clearly wrong. Please tell me, we are all here to learn and i always learn new things about the stuff i use :)

Is there any way to remove bindings from all bound elements on a form close event?

According to this document, the following code causes a memory leak in WPF:
myDataBinding = new Binding("Children.Count");
myDataBinding.Source = myGrid;
myDataBinding.Mode = BindingMode.OneWay;
MyTextBlock.SetBinding(TextBlock.TextProperty, myDataBinding);
The same happens if we bind some value in XAML:
<TextBlock Name="MyTextBlock"
Text="{Binding ElementName=myGrid, Path=Children.Count}" />
To avoid binding memory leaks we need to remove binding on the form close event like this:
BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);
Question:
Is there a way to remove bindings from all bound elements on form and child controls?
It seems I would need some recursive method here.
In WPF 4 you may don't worry about leaks when binding to an object even if it is not INotifyPropertyChanged or DependencyObject. This bug was fixed.
Anyway I suppose BindingOperations.ClearAllBindings will be helpful.
Keep in mind that the example given was very isolated and not typical in a binding situation. The referenced document outlines this...
The TextBlock control has a binding to
an object (myGrid) that has a
reference back to the TextBlock (it is
one of myGrid children’s).
The problem lies in the fact that the binding is taking place across UIElement objects AND one of the objects is a child of the container AND the propety being binded to is not a DependencyProperty. Again this is not typical as most binding occurs on an object/property which implements INotifyPropertyChanged.
If you have multiple bindings like this within your application then the approach should be to clear them out as needed when the given container closes as mentioned in the referenced document.
Another approach is to simply expose the data you need on your object being consumed by the View and disregard binding to the UIElement properties which are not of type DependencyPrperty. While this is not always practical it will alleviate you from the above mentioned problem.

WPF Binding XAML vs C#

I've got a strange problem - binding created through XAML (both ways by markup extension or normal) isn't working(BindingOperations.IsDataBound returns false and in fact there is no Binding object created). When I do literally the same from code everything is working perfectly.
One more thing is that the Binding in XAML is created in a DataTemplate - what's funny about that when I use the DataTemplate for the first time it fails, then I fix it from code (add binding to specific objects) and while adding more objects to the collection the binding set in XAML just works. If I try to remove all the objects from the collection and then add a new one the binding fails once again.
In reality this is a shortened version of another of my questions. For details please refer to:
WPF Debugging AvalonEdit binding to Document property
Sorry for doing it this way, but there's no answer and it's probably too long for anybody to read.
-
Is there any exception traced in Output window? WPF usually complains there instead of just failing the program.
The problem may be related to your use of IsAsync and some problem with the target property's handling of an invalid result. You might want to try getting rid of the IsAsync parameter or using a PriorityBinding to set a safer default to use while waiting for the async loading to complete.

Categories

Resources