WPF AutoCompleteBox Data Virtualization - c#

I am trying to implement Data Virtualization on a WPF AutoCompleteBox.
I found Bea Stollnitz's code here which works great on a ListView and I made it to work on an ComboBox easily, but there's no way I can seem to get it working right on an AutoCompleteBox.
To be precise, it works - the list is virtualized, items are not all loaded on startup - but what seems to happen is that the AutoCompleteBox iterates through all the items in the list as soon as the ItemsSource changes and this ends up breaking the whole thing (i.e. on load, all the pages in the list are requested, so even though they are virtualized, they will all be requested in the beginning and get loaded). My guess is that this is because of the filtering that the ACBox does, but I'm surprised that there's not way to prevent it, since the control does normally allow filtering to be done on the server-side using the Populating event.
I feel that I'm missing something, I can't believe that no one has done something like this before or that it can't be done, so I'm guessing that I'm just doing something obviously wrong that I can't figure out since I'm new to WPF.
Here's some of the things that I've done to try and get this together (based on Internet searches around similar problems):
I made sure all the conditions for the built-in UI virtualization are ok including explicitly turning it on, setting the max height of the ListBox etc.
I replaced the ListBox in the AutoCompleteBox with a ListView like the one that Bea uses in her example. Side by side, the ListView by itself works as expected, but the one embedded in the ACBox does not.
I tried using no filtering in the ACBox, using a custom filter, handling the populating evenet manually etc. This doesn't help. Making a custom filter is obviously not enough since the custom filter only allows you to specify the result of evaluating one item, the code that loops through the list is not visible so you can't prevent looping. Turning the filter to "None" doesn't do anything either.
Any and all suggestions are welcome!
The target for this is .NET 3.5 and I am using the WPF Toolkit (Feb 2010 release)
Thank you!

I tracked this down to OnItemsSourceChanged() (see source). In there, the AutocompleteBox stores a "local cached copy of the data", which is why I see the behavior noted above.
This is a private method, so no overriding here.
It seems to me that because of this you can't apply DataVirtualization to the AutoCompleteBox, at least not using the ideas in Bea's solution. If anyone has any different thoughts regarding this, I would love to try it out, but until then, this is what I believe the answer to be.

Related

Working with values in web forms scaffolding

I have recently been tasked with learning EF 6 and web forms scaffolding for our group. Most everything works perfect for me and even though I was ready to hate it I don't. There are a couple of things that I can not make work the way that I want them to. When I scaffold some CRUD pages it works great, but I want to set some default values on the Insert page. I am able to set values in the constructor or the properties, but they do not go to the insert page until the click event to add the item. I have tried every way I could think to figure out an annotation that would work on my object as well as in the Dynamic control. So far I can not make anything work. I can actually remove the dynamic control and add my own control and add it to the object in the insert method, but that just does not feel right. Is there another way of doing this?
Specifically the things that I am trying to do are to set a default date in some fields based on DateTime values over a 30 day period from creation time. I also have state and county dropdowns that are tied to more than just the object that I am working on. Currently I use EF6 and LINQ in my DAL to just populate the dropdowns with objectdatasources and they work great. I want to hook them as dynamic controls as well. I know I need the [DataType] attribute, but there is no dropdown option to choose from. Also I am not sure how to hook up the dropdowns to have the county fire after the state fires so that the counties will change with each state selection. Is there a tutorial somewhere that would cover these things. I have searched everywhere and can not find any guidance.
Thanks Jimmy
Since no one seems to know the answer I thought I would list the needed things to help you if you are having the same issues. If you need to work with the data inside a Dynamic control you are going to have to do a lot of conversions. You must find the Dynamic control in the container you are using and parse that to a dynamic control and then you need to dig into the control template of that control and find the textbox etc that you need and parse that into the needed control type and grab or set its value. If you are needing to keep your code secure and must pass Fortify or some other static analysis tool you will also have to encode the values because fortify can not see that it came from a control that was encoded. This becomes a pain in the butt and it is much easier just to go ahead and switch to a standard control and manually add that in the insert.
The line of code if you need to know how this would work is something like this.
((TextBox)(DynamicControl)fvName.FindControl("DynamicID").TemplateControl.FindControl("TextBox1")).Text;
I wrote this from hand so it might have something out of place, but this should get you on track.
Jimmy

WPF: slow template instantiation

I have a WPF application, and it's slow.
It is NOT the rendering. Firstly, the rendering is quite simple, and secondly, I looked at it with WPF Performance Toolkit - nothing.
It is NOT in my own code. Firstly, the unit tests work fast, and secondly, if I replace all DataTemplates with blank ones, everything works fast.
So far, it looks like the slow part is template instantiation. That is, when you start the application, and open some complicated screen, it takes a lot of time. And by "a lot" I mean "a lot". Sometimes can be as much as 3-5 seconds - for example, when there's a datagrid with 100 rows. But when you go to another tab, and then go back to that same screen, it opens fast (as long as its viewmodel stays put).
This is very annoying not just because it's slow, but because I can't do anything about it. If I had some control over the slowness, I could, maybe, display some "opening, please wait" message or something...
Besides, when I look at some other WPF applications (most notably, ILSpy), they seem to work reasonably fast, despite the large amounts of data. This makes me believe that I'm probably doing something wrong. But I have no idea where to start.
Any ideas? Any classic mistakes? Any tips?
My exerience comes from working on the WPF mind mapping application NovaMind
A couple of months ago we completely rewrote our intermediate layer to solve the performance issues we had experienced. In a nutshell, creating our user controls seemed to be way to slow. Unfortunately I couldn't find a great way to profile the performance as neither the WPF Performance Suite nor commercial applications such as ANTS Profiler give you any detailed information on this part of the WPF process. (I asked this question back then)
We resorted to manually test our application by trial and error and removed parts of our user controls to see what exactly is the culprit.
In the end we solved the performance issues by completely rewriting our controls. We also cut down on the complexity of our visual tree dramatically. Before the rewrite, one of our most used user controls, when inspected with Snoop, consisted out of 61 different things, now there are only 3. Wherever possible we only added things to the visual tree on demand. (As you know in XAML even when you set things to Collapsed, they need to be created first).
Finally we were forced to write our own rich text rendering control as the built in RichtextBox is ridiculously slow and the visual tree of the RichtextBox is quite complex.
I don't know if this will apply to your situation but I would recommend that you investigate your user controls and see if they are complex. Maybe you have things that you could trim.
Low hanging fruits would be parts that are only rarely visible or can be created in a lazy manner. You could create these parts from code behind when necessary rather than having them in XAML. This should help you a lot.
Otherwise virtualization is your friend, if possible. In our case we couldn't do that unfortunately.
This sounds similar to a problem i was having. I posted the fix here: WPF UI Automation issue . Just posting for the benefit of searchers, as it took ages to resolve.
Following comment on link only answer, here is the crux of that post:
I did the following:
Downloaded Hotfix - - http://archive.msdn.microsoft.com/KB978520 (may not be required)
Downloaded Hotfix - - http://archive.msdn.microsoft.com/KB2484841 (definitely required even if you have Windows 7 / .NET 4)
Improved the code further (the validation was causing an excess of objects) - Why does WPF Style to show validation errors in ToolTip work for a TextBox but fails for a ComboBox?
It may be that only Number 3 was required, but it worked. Just posting here so people dont lose the days I lost in memory profilers etc.
User Control in your data template, is not completely bad idea but if you crave for performance then you should consider switching to lighter control. For example, having a UserControl just hosting a TextBox is very bad idea, as UserControl is made up of ContentControl, ContentControl hosts ContentPresenter and ContentPresenter will host TextBox so if you notice your Visual Tree, it has three new layer of UI Elements. Reducing Visual Tree will certainly improve the performance.
Most likely, I would suggest creating Custom Controls that may be a completely a new control having few dependency properties that can relate to data you want to present and you can have its own custom template in generic.xaml. Second, you can just simply derive a control from existing controls and redefine its default template in generic.xaml.
This approach will certainly work better as you will be reducing your Visual Tree, thus reducing Visual State Manager's job.
Changing theme or template will be slower then changing the element that hosts content. And let the element have the default template in its own generic resource dictionary.
Try moving all the resources up as
far as they'll go, preferably into
app.xaml
Check if you could use StaticResource
instead of dynamic ones, static ones
are alot faster
If possible, try using depedency
properties in your VMs, especially if
you have alot of them at once or if
they have alot of properties. That will keep wpf from having to do a bunch of reflection.
You mention you are using a DataGrid with, say, 100 rows. A likely culprit of your perf problems is that whatever datagrid you are using isn't doing virtualization, and so your visual tree is gigantic.
Normally, long startup time in WPF screens points to a large visual tree.
I'm not sure if you're using a datatemplate per row, or some 3rd party grid that binds columns, or what - but lets say you have 8 columns with controls. Depending on your grid/validation/etc, this could be a visual tree of 20-60 items per row. If you have a combobox, then each item in the dropdown may be created per row as well.
To fix this just takes watching the details, and taking measures as you go:
Use a virtualizing control as much as possible. This means using a virtualizingstackpanel inside list controls, and making sure your 3rd party controls do as well (many stock WPF controls do now by default)
Do not overuse UserControls, composite controls, etc. Adding depth adds time, and putting in extra visual tree depth in a datatemplate or other repeated area adds up fast.
If all else fails, show a simple screen and add controls through code to improve perceived performance

Selecting multiple check edit boxes in a grid control

I'm trying selecting multiple check edit boxes when added as a repository item in a grid control, but at the moment it only allows me to select one at a time. So far I've seen that one need to unbound the checkedit's. But I don't know how to do this.
Does anyone have good examples or links of how I can get this working.
Because what I need to do is select certain option in the beginning of a process and then late display the exact same selections but still with the unselected ones
Thanks
The functionality you are asking about is the default one for XtraGrid, DXGrid (WPF). I believe that you are using XtraGrid and do not understand the problem you ran into. Everything should work properly and should not require additional adjustments. Could you please explain the problem in greater details. If the XtraGrid does not allow the end-user to edit its data, we need to know which DataSource you are using.

Displaying a Large Amount of Data

I'm working on a media library mock-up and I have a database of songs (over 9,000 tracks) that I want to display and make sortable. I'm not sure which GUI control would be best to use and I am not sure how it would be best to add all of the entries to the control.
Obviously using a listview and adding each entry one at a time takes a long time. Currently, the database is returning all of the tracks in an array of media objects (mediaEntry[] - a struct I defined). I don't know much about .NET's databinding system and any performance benefit that may bring.
The database is also searchable so I'll be changing the information displayed in the GUI control depending on the search terms.
Something like DataGridView or ListView in "virtual mode" should work well; this avoids the need to process all the data up-front.
however - I doubt that mediaEntry should be a struct - sounds like a class to me.
It is very rare you write a struct in .NET
The Listview control has a virtual mode, where you supply the viewable data on demand. Its actually easier to use than it sounds. Checkout the VirtualMode property and the RetrieveVirtualItem event.
You may want to give ObjectListView a try. It's very handy to use and has excellent performance when used appropriately.
Note: I'm not the developer of this library, I'm advertising it just because I used it in one of my projects.

What is a fast way to render a log view in WPF?

I'm writing an application that needs a log-like view, (similar to how an IM client displays messages in the conversation), with potentially many updates per second. Speed is an issue here; the application locking up due to a large number of incoming events is a possible problem. I need selection and basic text formatting, so manual rendering could get quite complex, I'd like to avoid it if possible. I'd also like to bottom-anchor the scroll bar, that is, if it's at the bottom, stay at the bottom when the new item is added. What would be a good way to implement this?
You can implement it very easily in WPF.
Create an ObservableCollection of Log entities and bind to a ListBox.
Give a DataTemplate for the ListBox.ItemTemplate.
*When running in real time you need either UI side or Data side virtualization
Check out my PaginatedObservableCollection so that the DataVirtualization will automatically function.
I think you should have a look at ListView/ListBox controls, they support UI virtualization and provide functionality you're looking for. Also you can improve performance by data virtualization/lazy loading - i.e. don't hold invisible items in memory and load required data on demand

Categories

Resources