Issues With ItemsContainerGenerator and Recycling - wpf

It seems I cannot figure out this problem on the internet well so I am asking you guys. I would like to know what is the difference between using ItemsContainerGenerator inside it's custom Panel's measure method with and without calling the Recycle on containers.
My guess is that generator creates new containers and connects them to data items once the method GenerateNext is called but does generator always connects item to their containers in GenerateNext method? With always connecting containers to items I mean, does it links containers that have been already generated/realized over again to their data items?
What will happen if I start recycling containers by calling the recycle() method. Would the generator then still always link containers to items?
I am asking this because the scrolling performance depends usuall on this. If the generator always connects items to containers that would mean it refreshes DataContext/Binding and scrolling would lag little bit. Though if by using recycle method the generator stops refreshing Bindings the scrolling would run pretty smoothly.

When you are using the Recycling virtualization mode, containers are reused, so they are nor necessairly connected to their origin data objects. So if your container template contains elements that will rebuild their visual tree on data (or its type or properties) change - they will. To improve performance I can suggest you to create as independent from data change template, as it possible, minimize visual tree. Also you can modify your ClearContainer method to prevent resetting some global values that are not depending from data: it can be a reference to some big parent control, settings - anything that usually constant but affects visual tree on change.

Related

What causes VisualTreeHelper::HitTest to return incomplete results, and sometimes no results?

I had a scenario where I was connecting to a Windows WPF app, through a network connection to drive UI for the purposes of test automation.
Sometimes my requests to the UI using VisualTreeHelper returned no results regardless of the apparent state of the logical or visual trees.
This, more than a question is the documentation of the solution to the problem.
It turns out that I was detecting the network connection availability and IMMEDIATELY after it responded, I issued calls that exercised VisualTreeHelper and catching the UI while being rendered. The result of that call was incomplete and subsequent calls failed completely (no elements were found ever).
My practical solution was to delay for 2 seconds between when the communication was open, and the first call to VisualTreeHelper. That eliminated the weird state caused by calling UI too soon. I tested with 100 iterations of the app rebooting with no problems.
I 'Googled' the problem but didn't find good results.
Interestingly, I asked ChatGPT about it and it informed me:
"If you try to access elements of the visual tree before they have been fully rendered, you may get unexpected results, or an exception may be thrown."
I asked the bot to tell me what sources it had for the assertion and the only link I got:
"here's a link to the Microsoft documentation that mentions the risk of calling VisualTreeHelper before the visual tree is fully rendered:
https://docs.microsoft.com/en-us/dotnet/api/system.windows.media.visualtreehelper.getchild?view=netcore-3.1#remarks"
Unfortunately such link actually doesn't mention anything like that. This may be due to ChatGPT using 2021 data, and the link content has changed.
A friend suggested I used archive.log (an Internet archive) to see if a previous version of such link had the desired information, but none was found.
ChatGPT provided relevant information, but could not provide sources where it distilled it from.
Lastly, I acknoledge that the 'ideal' way to address the problem of racing to use VisualTreeHelper before the UI is done rendering is to wait for an event the main window calls:
private void MainWindow_Loaded(object sender, RoutedEventArgs e);
and gate any use of VisualTreeHelper until this event is raised.
My approach is not stricktly the ideal, but practical with little effort. The 2 second delay does not significantly impact my scenario.
After I delayed 2 seconds before using VisualTreeHelper to wait for UI to render, I had no problems.
The short answer is (as you have observed) that they're not there yet when you try finding the controls.
The visual tree that the visual tree helper works with is the object graph of UI controls etc which are within a window.
A window is a content control.
When you instantiate a window, the window itself is created using the constructor.
I'm not sure there's a point where there can be just the window itself in the visual tree but this is conceptually how it works.
Parent windows is first then the root panel content and the content of that root.
The "tree" of controls is window > content panel > child controls.
Constructing a window can take a while. 2 seconds seems kind of slow but developers are prone to putting all sorts of things in constructors. The time taken may vary depending on how much code the developer has put in there, connectivity speeds etc etc.
That variance would explain why a test result will vary.
The correct event to handle for a window would be contentrendered. As the name suggests, this fires after all the content of the window has been rendered.
With a usercontrol or page you can handle loaded but you're best deferring processing via use of dispatcher. Loaded doesn't guarantee everything is rendered.

What is the best way to identify updated items in an in memory list?

I'm using Siaqodb for my client side database engine in a Sync Framework silverlight project. I've switched to siaqodb because microsofts client side solution loads the entire database into memory at once and, as such, has a hard time handling large data.
I've bound a list of SiaqodbOfflineEntity objects to a silverlight datagrid in order to create an editable datagrid. Unlike microsofts solution, you can't bind the database entries directly to the datagrid. You have to query the database and bind a list of in memory objects to the datagrid. This causes a problem in that the database isn't immediatly updated when the datagrid cell is changed. I'm trying to find the best way to handle updates to the database after a change in the cell. I can't just update each item to the database because the siaqodb engine will mark the item as dirty even if no change was made to the object. This will cause conflicts when trying to sync. holding a cached version of the original list and then comparing each property of each object to find which ones have changed seems like it would work, but seems to be a bit cumbersome. I've also tried looking at some of the datagrids events but RowEditEnded doesn't appear to fire when a cell is edited and CurrentCellChanged seems to fire whenever I switch rows (odd).
There's got to be a better solution to this. Anyone have any ideas?
So I've gotten this to work by changing my offline entity classes to implement iNotifyPropertyChange and I think this is a reasonable solution. I set the PropertyChanged event to a function that saves the object to the database. There is a VS package called notifypropertyweaver that will inject this code at compile time, reducing the amount of work needed to be done on auto-generated entity code.

Best way to update Locations dynamically in Bing Maps using Silverlight?

I'm developing a test application in which I need to:
a) Draw some paths from downloaded data. I have a REST/JSON server whith these data and my little app can consume it without any problem. The paths are downloaded once and that's all.
b) Draw pushpins, circles, whatever at some locations BUT their locations can change in real-time. The Silverlight app must ask the REST server for updates in these points in order to update the shapes in the map. The REST provides the "last know position" by default, so this location is what I want to display dynamically.
My question is: which is the simplest way to achieve b)? I'm quite a rookie at Silverlight, so I donĀ“t know if it has some 'automatic-obvious' way to do this automatic update. Do I need some 'timer' to consume the service, a local list of locations and bindings between shapes and these locations?
Thank you in advance!
I would say you're on the right track.
I would create an ObservableCollection of a data model that represents the locations, and bind that to the Bing MapControl. Then create a DataTemplate (probably based on PushPin) that will visually represent how you want the data point to look on the map. The paths can be created with MapPolyLines
Since you're communicating with a REST server, I think your best option for updating the points to have a Timer object like you mentioned, and perform a call to update the ObservableCollection every time that fires.
Hope this helps!

detecting gdi / user handler leaks in winforms

I did nice winforms 2.0 application and it's working great and customers are still happy but unfortunatelly I cannot solve one issue. The problem is that after using app for a couple of hours, gdi user handles number is rising and rising and finally process cannot allocate more objects and app crashes...
I'm not doing anything fancy, it's regular app, a few forms, a few more modal forms, a few datagridviews and a lot tablelayoutpanels where I'm adding a lot labels and textboxes.
My questions are:
are there any "recommended-practises"
concerning adding/removing regular system
controls on forms at runtime (dgv/tlp)
how to detect system handles'
leaks - preferably using visual
studio and a kind of free plugin
(profiler?)
Detecting graphics and window handle leaks is very difficult. As to a particular strategy for finding them at runtime, I can't suggest anything (though I'd love to hear someone else's!).
As for preventing them, here are a couple of reminders:
While the Control class's finalizer will call Dispose(), this is non-deterministic. You are not guaranteed that ANY object will EVER get finalized by the garbage collector. It's likely that it will, but it's not a guarantee.
In keeping with the above, Forms are an exception. When a Form is shown in a NON-MODAL way (meaning through Show(), NOT ShowDialog()), then when the Form closes it will deterministically call Dispose(). Forms that are shown through ShowDialog() must have Dispose() called manually in order to deterministically clean up the control handle.
Keeping those two things in mind, the most important thing that you can do is to ensure that you always call Dispose() on any object that you explicitly create that implements IDisposable. This INCLUDES Forms, Controls, Graphics objects, even the graphics helper classes like Pen and Brush. All of those classes implement IDisposable, and all of them need to be disposed of as soon as you no longer need them.
Try to cache your graphics utility classes, assuming you're using some. While a Pen and a Brush are fairly lightweight to create, they do take up handles and need to be disposed of when you're finished. Rather than creating them all the time, create a cache manager that allows you to pass in the parameters that you would use in the constructor for those objects and keep that object around. Repeated calls with the same parameters should still only use one single instance. You can then flush your cache on a periodic basis or at specific places in your application if you know where those would be.
Following those guidelines will greatly reduce--if not eliminate--your handle leaks.
I find that using the Task Manager with the GDI Objects column visible essential to finding such leaks. You can target specific areas by breaking before the call, make a note of the GDI objects, then break after the suspect call to determine if the objects are being released properly.
The source code for two useful GDI leak tracking tools can be found here: link text
I have used it successfully on many Visual Studio C++ projects. I am not sure whether I work with .NET as well.

Am I a discoverer of a bug in the WPF engine?

We have a MFC 8 application compiled with /CLR that contains a larger amount of Windows Forms UserControls which again contain WPF user controls using ElementHost. Due to the architecture of our software we can not use HwndHost directly. We observed an extremely strange behavior here that we can not make any sense of:
When the CPU load is very high during startup of the application and there are a lot live of ElementHost instances, the whole property engine completely stops working. For example animations that usually just work fine now never update the values of the bound properties, they just stay at some random value after startup. When I set a property that is not bound to anything the value is correctly stored in the dependency property (calling the getter returns the new value) but the visual representation never reflects that. I set the background to red but the background color does not change.
We tested this on a lot of different machines all running Windows XP SP2 and it is pretty reproducible.
The funny thing here is, that there is in fact one situation where the bound properties actually pickup a new value from the animation and the visual gets updated based on the property values. It is when I resize the ElementHost or when I hide and reshow the parent native control. As soon as I do this, properties that are bound to an animation pickup a new value and the visuals rerender based on the new property values - but just once - if I want to see another update I have to resize the ElementHost.
Do you have any explanation of what could be happening here or how I could approach this problem to find it out? What can I do to debug this? Is there a way I can get more information about what WPF actually does or where WPF might have crashed? To me it currently seems like a bug in WPF itself since it only happens at high CPU load at startup.
I don't do any work with those techs, so I can't really speak to that. However, to me it sounds like some kind of deadlock is occurring in your code which is blocking calls to redraw() (or its equivalent). Resizing the window will force a redraw, but your normal mechanism for telling it to redraw when you've changed something might be blocked.
Is it possible you have a race condition in your code somewhere? On a lightly-loaded system things might happen in the correct order, but on the heavily loaded one the timing might be different. Perhaps that's triggering a deadlock in your code?
If you can attach a debugger, take a look at the threads that are running. If you can see what each thread is waiting on and what else it holds locks on (You can do this with Java, not sure about your app) that might help you determine where it's dying.
There is no detail on how you load your data on startup... If you haven't done it yet, consider using Dispatcher.BeginInvoke (with a priority lower than render) or a BackgroundWorker
Here is a post on how to do this!
PS. Just be careful if your objects that you bind to is an ObservableCollection<>... Read more about the issues I had doing this here
Most of the time, select isn't broken (as the saying goes).
It does sound very much like some kind of race or deadlock as #Herms suggests.
You could of course check MSDN for known bugs. Depending on what your code is like, when I'm really stuck with a bug I find that removing chunks of code until you're left with a minimal test case usually helps.
Nothing strange happens in your application. Dependency system "stops working" because of the fact, that UI thread, all the system relies to is busy. It's all about priorities for different Disparcher objects. I can consider you to use background processes doe for prolong operations, while all synchronization done in UI thread.
Also, you can play with task prioritization (DispatcherPriority enum as first parameter of Invoke/BeginInvoke methods)
Another tip, can help you is to implement DoEvent pattern, known from WinForms (to process messages in windows queue)
To summarize, you should remember, that you're working in STA. Also, when you're using ElementHost in Windows XP, you actually remove hardware acceleration. Try to use .NET 3.5 SP1 to fix it somehow, but still you have to leave CPU for rendering and dispatching things.

Resources