I have a WPF application that renders input forms based on form-configurations saved in a database.
The forms have many controls (100+) and most of these controls are derived from a TextBox-control. On some machines (fast Hardware, Win7 32Bit, also some elder, Windows XP 32Bit), after entering data to a lot of these forms, input performance goes down. Every keystroke gets a delay of some milliseconds and the only solution to resolve this is to close the application and restart it.
My derived control overrides the metadata of the DefaultStyleKeyProperty to set a custom template.
I'm currently reasearching the app in SciTech memory profiler, but maybe someone has already experienced a similar problem with derived TextBoxes and can give me a hint and spare me some more hours/days investigating the problem?
Update
Look also here
It sounds like you may have something stopping the controls on the "used forms" being GCed.
Firstly opening and use as many forms as possible looking at the windows task manager to see if you memory usage is going up – if it is not there is no point looking for memory leeks
Check you are removing all events handlers you forms/controls have put on any long lived objects.
Check that any objects you databind to implement INotifyPropertyChanged, see KB938416
I have in the past had good results using the Red Gate memory profiler.
You don’t need to have controls created that the user can’t see, 100+ controls will have a cost.
Can you use something list a list control in virtual mode, so your TextBox controls are only created when visible.
Related
In my program, there is a map editor, after loading the information from the database, I need to generate some custom controls (6000-10000 depending on the map). Unfortunately it locks the user's screen for 10-20 seconds.
How can I do using lazy loading? How can I do without crash and lock screen?
This question is much to broad. But i can give you a number of hints.
First of all i'am pretty sure you don't need so many custom controls. Think about how many input devices the user has, he can't interact with that many controls at the same time. So you can "cheat" about these controls in a couple of different ways. For example, display an image of the control, and switch it if the user starts to interact with it.
Another thing is, you don't need what you don't see. Why create a list of 10000 Elements if only 10 will fit on the screen? There is no reason, thats why there are ways to mitigate that, one is called Virtualization which can be done in a number of ways. You can use UI Virtualization, by defer the loading of the ui components or use data virtualization.
Another thing, in cooperation with data virtualization is to use threads or a background worker to handle the load of that much data. Create your data in batches to give the UI Thread time to handle the windows messages.
Look into Binding or doing the work in a Background thread?
If they are in a ListView, look into VirtualMode:
http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.virtualmode.aspx
What are you loading these controls into? Are you doing it in the UI thread?
Use TPL (Task Parallel Library) to do the DB tasks on a separate thread... it looks like this:
Task.Factory.StartNew(() => MyLongRunningMethod));
Check out this great article over on CodeProject for more information...
EDIT: As noted below the original answer implied that somehow controls can be generated on a separate thread but in reality as a part of the visual tree and therefore the UI, controls must be generated on the UI thread so that was not a valid suggestion...
EDIT: Don't see how it would be possible to fit 10000 custom controls on a signle screen so there must be a way to use some type of virtualization schema where only visible controls would get generated and the rest of the controls would get generated on demand...
I have a C#.NET winforms project, and some controls are moving in design view whenever I build the project. Its only some of the controls (a panel with a label and datagridview in it, a button, a link button and a label) are all moving up on each build.
Has anyone seen this before or know how to fix it?
I think it is because of the AutoScaleDimensions. My guess is that your form was originally created on another machine.
Per MSDN.
"The AutoScaleDimensions property represents the DPI or font setting
of the screen that the control was scaled to or designed for.
Specifically, at design time this property will be set by the Windows
Forms designer to the value your monitor is currently using. Then,
when the form loads at run time, if the CurrentAutoScaleDimensions
property is different from the AutoScaleDimensions, the
PerformAutoScale method will be called to perform scaling of the
control and all of its children. Afterwards, AutoScaleDimensions will
be updated to reflect the new scaling size."
My guess is that for odd some reason when you build you project property (maybe some others) gets adjusted, but not on design time.
I think about few possible reasons:
You work on multiple monitors and/or there is some odd stuff with your adapter.
There is some problem with auto-generated designer file. Maybe it
edited manually somehow.
To fix I propose to do something I would do:
Recreate form from scratch if possible, by copy-pasting bits
one-by-one.
If not take some merging tool and insert fresh form
properties.
Also here is another interesting question on AutoScaleDimentions.
I am building a rather large WP7 application and having a lot of fun with it. It is Pivot based and has quite a lot of pivot pages. I dynamically add and remove pivot pages based on what "mode" of the application the user has selected to keep the application look and feel as simple as possible. All is going quite well so far my app is fast responsive, not a memory or resource hog and performs background loading on demand when needed.
The Model layer contains all my business logic that represents what the application is all about. It is clean and separate from the the view-model and view layers.
The View-Model layer is an abstraction of the model to the extent that it needs to interact with the view and also contains the session-ness and workflow aspects of the application in general. It contains objects which represent the Model in a way the View needs to interact with. The view model persists the state of the application in isolated storage and supports tomb-stoning.
The View layer contains a lot of elements pivots, user controls, styles, resources etc in both xaml and the corresponding code behind. I do like Blend and the Xaml designer within visual studio 2010 however I find myself still coding/configuring the view objects within the code behind due to the nature in which they interact with each other. The code behind of the view objects is becoming quite large but still only reflects the state of the view and not the state of the application. I have made use of user controls quite a lot as this lets me build reusable components across many pivot pages however the user controls are not Blend friendly. What I am worried about is that my view might becoming more complex than it needs to be and losing the ability to coordinate the user interface design with tools like expression blend.
By customising the view this way and making use of reusable controls I have reduced my Xaml considerably and don't suffer from bloated Xaml files that other developers have mentioned but lost ability to co-ordinate with Blend. Is there are happy medium to be found? Should I be looking at designing custom controls?
[Edit]
Thanks for your reply. I think it boils down to either a lot of Xaml with a designer or break it down into user controls with more code behind. Since I moved into user controls my mindset has moved back to doing things by hand rather than with a designer (better the devil you know right!). My thoughts are should I make my user controls into skin-able custom controls or just keep going how I am and avoid using the designer. Its a bit of potato-potardo but I don't want to get into bad habits.
Custom Controls (or Templated Controls) are not directly related to your question as far as I can see. Custom controls are just controls that add new properties, events and methods to an existing control and are still capable of being 'templated' by a designer.
Creating UI in code does make it harder to design the application using Blend (and even the VS designer) because the only way to see the interface is by running the application.
A lot of the logic that creates the UI could possibly be replaced by using the Visual State Manager. Use states of the controls to design them for specific modes of the view. Only when you need extra/new states you will have to create a Custom Control.
As your question is a bit wide, feel free to add comments or extend your question so I can add more details or remove this answer when it is utter nonsense :)
When hosting WPF user controls within a WinForms MDI app there is a drawing issue when you have multiple forms that overlap each other that causes very distinct visual artifacts. These artifacts are mostly visible after dragging one child form over another one that also hosts WPF content or by allowing the edges of the child form to be clipped by the main MDI parent when dragging it around. After the drag and drop of the child form is completed the artifacts stay around generally but I've found that setting focus to a different application's window and then refocusing back on to my application window that it is redrawn and all is good again until the child forms are moved once again. Please see the image below which demonstrates the problem.
Those at Microsoft insist that the WinForms MDI is already a sufficient solution for MDI and doesn't need reinventing in WPF although I find it hard to believe they tried creating a WPF app this way because of the obvious shortcomings.
UPDATE: A few extra notes that I left out is that if I create these Forms without setting the MdiParent they are created as regular forms and this issue doesn't happen. This issue seems unique to the WinForms MDI scenario. Also I've currently running on Windows 7 Enterprise and I'm aware the results may be quite different on Windows XP but I haven't been able to test this.
UPDATE: I've found a few other related resources on this issue that I thought I should share.
elementHost repaint problem in MDI
application
elementHost repaint problem in MDI application on Tech Archive
It appears that another workaround is to revert to software rendering as opposed to taking advantage of hardware acceleration. This was the suggestion by Marco Zhou on the MSDN Forums.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.Loaded += delegate
{
var source = PresentationSource.FromVisual(this);
var hwndTarget = source.CompositionTarget as HwndTarget;
if (hwndTarget != null)
{
hwndTarget.RenderMode = RenderMode.SoftwareOnly;
}
};
}
}
I've tested this and this solution seems to work very well and so far is the only solution that I've found for solving this problem within a FoxPro interop scenario which is very similar to the WinForms one I posted about originally. For now I'm planning to use my original Refresh on the MDI Parent solution for my WinForms project but then for my other native interop applications such as when my WPF controls are hosted in Visual FoxPro I'll use this solution. That is unless of course if a more elegant solution is discovered for either of the cases.
Also it's important to note that from what I'm aware software rendering is the only option on XP systems and normally Visual FoxPro nore WinForms normally take advantage of the same type of hardware acceleration that native WPF apps do on Vista OS and up. So using this option may not be as bad as it sounds when you do have to deal with interop. Currently I'm not aware of any related side effects when using this solution but if there are any those would have to be taken into serious consideration.
Well, I may have found a solution although it feels like a bit of a hack. It appears that if you call the Refresh method on the MDI parent whenver a child MDI Form is moved that the noted artifacts go away. Visually things appear a bit jittery when dragging a window but it seems much more acceptable than the example I showed in my original post.
private void Form1_Move(object sender, EventArgs e)
{
this.ParentForm.Refresh();
System.Diagnostics.Debug.WriteLine(string.Format("Form Moved to: ({0},{1})", this.Left, this.Top));
}
I've tried many combinations in the same vein such as refreshing just the child window that was being moved by calling methods such as Update(), Invalidate(), Refresh() and also I've tried these same methods on the MDI parent as well as Dispatcher.Invoke(DispatcherPriority.Render, ...) and InvalidateVisual() on my hosted WPF control but none of those other methods worked accept for calling Refresh() specifically on the MDI parent.
I realize that this probably isn't the optimal solution since I'm forcing the whole main application window to refresh every time a child window moves a few pixels but as for right now it's the only reasonable solution that I found that works. If anybody else has any alternative solutions or any improvements upon this I will gladly accept your answer instead.
Check video drivers and try disabling hardware acceleration. Most artifacts are caused by bad drivers, failing video card, or insufficient time to complete the refresh.
First troubleshooting step: Update video drivers. Obvious, I know.
I had similar issue, checking my video card settings (NVidia Control Panel) showed global setting set very high causing a longer refresh interval which may be aborted if taking too long. Setting my settings back to defaults resolved most of the issue. But I also run hashing programs which use the GPU intensely so this is likely the cause of my remaing artifact issue which is very seldom now and mostly shows its ugly face in Visual Studio.
Another troubleshooting step I ran across is to disable hardware acceleration for WPF, this can be done in 'HKEY_CURRENT_USER/SOFTWARE/Microsoft/Avalon.Graphics', or maybe an application can do it BUT this is only for troubleshooting; never set these within an application because it will disable for ALL WPF applications. I do not have this registry setting nor did I add it so I am not sure of the success with it, but many say this resolved their issue. Also note some applications have this option available, try disabling it if available.
Another troubleshooting step is to make sure the video card is a proper tier level for rendering. Any card that supports DX9 or greater should be sufficient, but other factors are involved (as is my case) so just because it is on the list does not mean it is adequate for your purpose.
Finally, you can use the Visual Profiler (part of Windows SDK), and other tools, to help determine what is going on more precisely with WPF lacking performance in relation to graphics ability.
Rendering Tier level notes and WPF Performance information --> http://msdn.microsoft.com/en-us/library/vstudio/ms742196(v=vs.90).aspx
Hope this helps someone.
--Ryan Strassburg
Your usercontrol or window loaded event ;
this.WindowState = System.Windows.WindowState.Minimized;
this.WindowState = System.Windows.WindowState.Normal;
it may seem bad solution. no need to hit your head against the wall.
A Turkish proverb says: the best code is the code is running :)
Visual Studio 2008 does a much better job of detecting and adding controls from projects to the toolbox for use in the forms designer. If you have an assembly with a UserControl- or DataSet-derived type, then it will automatically detect and add that control to the toolbox for designing forms. This is slightly better than the old system in 2005 that made you manually add controls and would occasionally forget them, etc.
However, on the legacy, monolithic project I am working on (now upgraded to vs2008) this means many controls that I don't want and don't need (and a redesign would not be warranted against so much legacy code :( ). I imagine that if I made certain types internal or private, then they wouldn't show up. However, I need many of those to remain public, but not show up in the toolbox. Furthermore, with so many controls getting added to the toolbox, opening the winforms designer slows significantly.
Is there an attribute or other mechanism that prevents toolbox appearance (that wouldn't otherwise affect functionality) ?
Would filtering using such a mechanism improve performance while still autodetecting new types that SHOULD be in the toolbox? (I know you can disable the autodetect, but its nice to have in many cases)
Have others encountered this irritation on large solutions (with many csproj/vbproj files)?
Edit: Thanks everyone! I knew it had to be simple (and was likely an attribute) but that fills the gap. Nice to know that I was in good company in not knowing about ToolBoxItem(false).
The following attribute should hide it from the toolbox:
[ToolboxItem(false)]
If you apply it to all the types you don't want to show, it will still show any new ones you create without this attribute. Note, you may have to manually remove the items to start with.
This blog post shows some other attributes you may want to use.
Go through the toolbox and for each custom control that you see that you want to hide, add the following attribute above the class:
[ToolboxItem(false)]
Of course, this is a compiled attribute and will affect everyone using the code, so I only recommend doing this for controls that don't make drag-drop sense. Otherwise, you will probably make someone that loves that control very very angry. :)