User control accumulates dependency property bindings - c#

I have a user control which is a labelled combo box, through debugging I noticed that each time I open the view which contains the user control there is one more get request to each of the models properties than the previous time!
I do re-instantiate the model each time the view is opened (for reasons that don't really need mentioning), but what appears to be happening is that the binding to any previous copies of the model are retained and the model seems to not be being disposed of correctly because it is still tied into the program through this binding! I appreciate that multiple bindings to the dependency property can be sustained, but how do I stop this happening?
Two considerations I have thought of:
1) The usercontrol is not being disposed of when the view is closed, if this is possible should I turn my attention towards ensuring it is being disposed of? Or is this overkill to the needs of WPF?
2) Instead of re-instantiating the model each time the view is opened should I just implement a copy function in the model base class which transfer all of the properties over opposed to actually creating another instance of the model?
What do you think?
Thanks

Finally fixed this problem, the issue was not limited to my user controls but in fact all controls (including the standard WPF ones) with bindings! When the window was being closed the bindings were not being terminated, this bug/issue/design (maybe it has a use - although I can't see what that would be) seems very strange to me. Initially I did think maybe it was the way I set the bindings up, however with one of the bindings to a normal text box I simply use Text="{Binding name}" - no other configuration defined which could be causing this issue!
Anyway, the solution I found was to add BindingOpertations.ClearAllBindings(this) to the windows closing event. Hope this helps if you are having this problem.

Related

VS Design Time DataContext (Sample Data) Contains Exception

Application
It's a WPF application meant to send files between clients. I'm working on a usercontrol meant to show a list of sent files, their recipients, etc.
Setup
I'm trying to style the control, but I need sample data to populate it. Following these instructions, I create a SampleFilesSource.cs that extends DataSourceProvider. It generates an instance of the view's viewmodel populated with an ObservableCollection of random recent files.
Next, in the view, I set the design time DataContext with this:
<d:UserControl.DataContext>
<sample:SampleFilesSource/>
</d:UserControl.DataContext>
But nothing shows up... What happened?
The Data-Bound Exception
Well, let's see. The Data pane in Blend allows us to see what's in the design time DataContext that's available for binding. Let's take a peek.
Well that's interesting. There's an exception in my DataContext. The Data pane doesn't show you any of the values, just what fields can be bound to. So how do I get a peek at the exception's Message? Can I bind to it?
Binding To It
Unfortunately not... In fact the only binding I can get to output any text is "(Collection)", when I try {Binding Data.RecentFiles}. The fields are visible under the Data object, but nothing has any values.
But what if I set the run-time DataContext to the sample data generator? Just remove that little d: from the DataContext tag and debug... Still no luck. By taking a peek at the live visual tree I can see the DataContext is bound to an instance of the viewmodel. And interestingly enough, the only thing in the datacontext this time is an Error field.
There's no Data field at run-time and the Error field is an instance of Exception. I think it's null. The property explorer just has an empty box, with no options to view it. I think it's weird that no unhandled exceptions showed up in the debugging session. It got stuck in the DataContext somehow?
Debugging
So other than clean, rebuild, restart VS, restart the computer, and whatever else I had already tried, what else can I do to get a peek at that Message? Here's a handy little guide to attaching a debugger to Visual Studio's designer process. Pretty cool!
I can only learn a couple things from the debugger:
My viewmodel being generated by my DataSourceProvider is valid, looks good, no exceptions thrown.
My DataSourceProvider's Error field is null when it leaves my code.
So all I can say that the exception occurs after I've called DataSourceProvider.FinishQuery, and before the designer gets it's hands on the generated DataContext.
Conclusions
I'm stumped. Any ideas?
Update
I created a minimum example to share, and sure enough the exception does show up in the Data pane in expression blend. However, I can actually bind to the generated sample data in the example, so now I think the exception was a red herring and my problem is elsewhere. I'm not even sure if there is an exception, and the Data pane just shows what it does because there COULD be an exception there.
Here's the example if anyone else wants to peek.
Can you show some code?
You can look at the problem in a simple way, you can try to bind a single value. If successful, you can prove that your binding part is no problem. Then you can start with your data template.

Create Single Window Navigation in WPF

I want to create a kiosk mode application using WPF. I want to use a single window because the user should not be able to exit this fullscreen application.
The application should guide the user trough a process. When the user proceeds trough the process, the screen should constantly change and show him the next step.
Usually I just create a single window and use a "state machine" to switch UserControls containing the information for the current step. Is there a better way to achieve this functionality? Maybe I would get a better result using multiple windows or Pages (never used them).
The reason why I am asking is that in future I want to have a simple, clean way of switching the content inside a single window. i.e. I am planning to implement some sort of animation when switching content (like sliding to the next / previous step). I don't want to put more effort into my current approach if it isn't the most flexible and clean one.
Any ideas?
PS: This is about desktop applications. Today I come from the Winforms environment and am experimenting with WPF.
There's a few ways you can achieve this.
First would be to use a Page based application, this will allow you to use a single window. Here is a pretty interesting tutorial
A bonus of using this approach is that navigation between pages is built in.
Your requirements are that you need to use animation for transitioning between pages, as far as I'm aware, using a Page based application cannot achieve this (I may be wrong). So your other option would be to use a UserControl MVVM approach.
This probably won't make a lot of sense now, but here goes:
You can use a single master view model which will hold multiple child view models, each of these could have a visibility property which dictates the visibility of the associated view. The master view model would simply be responsible for displaying the appropriate view model depending on where the user currently is in the application.
Using some clever XAML, you can create storyboards (animations) when the view becomes visible, which will allow you to achieve the crazy awesome animations that you require.
Anyway, that probably didn't make any sense, so here's a tutorial to get you started with MVVM.

Window content change: Specified element is already logical child

So I realize this is an often-asked about error, and I've read many results from google, but I still can't figure out how it applies to my situation.
The setup: I create a window to present views. I create an instance of the first view and set the window's Content property to the view. Currently each of my views is a window itself. This is working perfectly on 7/10 computers. However, for some reason on a few computers (verified correct .NET version), switching to the second view (creating an instance of the second view and setting the window's Content property to the second view) throws a System.InvalidOperationException Specified element is already the logical child of another element. Disconnect it first.
I read that using ContentTemplate instead of Content would solve the problem, but that just produces a blank screen instead of the second view (I'm sure I'm doing that wrong).
I've also read that you should use a UserControl instead of a Window as the Window's Content property, so I'm trying that (I don't have a computer that's getting this error, so I have to wait to hear back about success). But it seems to me that that won't really change anything.
Any ideas why this is only happening on some computers, and any ideas on how to fix it?
Edit: Changing the views to UserControls did not solve the issue
Edit: I realized that I misspoke. I don't set the Content of the main window to a Window, I set it to the second Window's Content. So like:
MainWindow.Content = nextScreen.Content;
Thanks for the answers everyone. I discovered that changing my views to UserControls was the correct path. When I tried it the first time I made this mistake:
window.Content = userControl.Content;
instead of
window.Content = userControl;
which still worked on my machine, but continued to fail on the computers that were previously having problems.
I still don't understand why only a handful of computers were throwing an exception over this. Obviously there is some difference between them, though it wasn't anything obvious like Windows version or processor architecture.

Bubbling Events from UserControl using MVVM in WPF..?

First of all, I want to let everyone know that I'm very new to the MVVM concept, and have looked pretty extensively for some explanation of what I want to do, but to no avail.
In the program I'm working on, I have a UserControl with a few buttons on it, which need to control the navigation of the main window. I have 3 different "pages" I want to be able to switch between in my main window. Instead of pages, I decided (for whatever reason, correct me if this is not the best approach) to use a UserControl for each page, and switch the visibility to the correct one. I need the data to persist while switching, so I don't believe that creating new instances of the Usercontrols will work.
My question is: How can I bubble the events from my "NavBarView" to the main window in a way that will allow me to switch the visibility, but in a MVVM way? I know I may be completely going about this the wrong way, and I'm happy to take any suggestions on a better way of achieving this navigation.
I have to use WPF, so WinForms is not an option. Too much transparency and custom controls for WinForms.
I would make the "NavBar" part of the main window if possible and use that to control the sub controls in the forms. I would be careful nesting User Controls. If you can avoid it I would (key indication is are you going to reuse it somewhere else). I took over a project a while back that had a main window with 3 separate highly coupled user controls that had to all work together and it was a nightmare. The only way I could get it to work somewhat safely was to have them all set their data context to the same view model. If I had to do it from scratch - would have taken a completely different approach with a single view.

WPF: UI Composition

I am working on a WPF app and the UI is getting a bit complex to manage. I am looking for advice on how to maintain it as it grows.
The layout looks something like this
<Grid>
<List of Objects View/>
<Objects Relationship View/>
<Object Details View />
<Multiple Objects Details View/>
<View 5 />
<View 6 />
:
:
</Grid>
Each view gets created (visibility hidden) and bound to some complex data, when the window is constructed. I want only one view visible, to the user at a time. I do this by manipulating visibility.
But the problem is the transition between views doesn't involve just fliping Visibility. It involves rebinding with currentdata, stoping background threads/timers and starting new ones (and possibly some binding again) that support the newly selected view. So what's happening is with every new view I add, I am adding a whole bunch of code to take care of all the possible transitions.
Is there some pattern I can use to deal with this kind of scenario?
Also is there some way I can avoid creating and hiding everything at app load and using visibilty as a controller?
Any help is greatly appreciated. Thanks!
May I ask how you are allowing the user to switch back and forth between the views? Is it a key combo? Mouseclick?
Not that it's answering your question per se, but my suggestion is that this sounds like a perfect scenario for a tab control. And with WPF, it doesn't necessarily have to look anything like a tab control.
If you use a TabControl, it opens up the possibility of using the SelectionChanged event coming off of the TabControl to allow you to tell background threads to stop and you can unload anything that you need to unload.
Depending on how you use the TabControl, the UI can be somewhat virtualized. What that means is that whenever a tab is unselected all of the UI for that tab is destroyed and recreated the next time it's selected. It will behave this way if you use the MVVM or PresentationModel pattern and load ViewModels as the items for your TabControl and use DataTemplates for the views. If you just put TabItems into the TabControl with controls inside of them, it will not behave this way, however.
As far as patterns are concerned, I'd definitely recommend MVVM. It may take a bit of time to catch up to it and understand it, but I'd never do WPF without it. If you need anymore resources or examples, let me know.
edit:
I reread your question and noticed that you may be in need of another type of navigation. If you've got views that are needing to make transitions to other views based on user actions and you don't want all of the views to be presented to the user so that they can select which one they want to look at (like the TabControl will do), you may want to look at WPF Navigation. Navigation is basically something that MS added in with WPF to allow browser style navigation in a WPF app. This MSDN article should be a good resource on that kind of thing.
This sounds like a problem well suited to Composite WPF (Prism). You can define your main area as a region, and use a SingleActiveRegion to show one view at a time. If you create your own region adapter, you can do all the maintenance when the active view changes.
Also, adding a new view won't involve changing the hosting view's code. This will allow you to deploy additional views in the future in separate assemblies...

Categories