I have a WPF application made up of around seven user controls, each with a variety of different controls on each (textbox, combobox, radio button etc).
Across the entire app I have applied a set of control styles take from the WPF Themes on CodePlex, however I have noticed a bit of a slowdown on the app since applying these styles. The ResourceDictionary containing all my styles weighs in at nearly 300kb in code size.
Would there be a benefit to gain by splitting the styles in to multiple Resource Dictionaries and only merging the styles that each usercontrol requires rather than the all the control styles even if they are not being used.
How does WPF load styles in to memory? When required or is the whole ResourceDictionary loaded in to memory at startup?
When an object is created from XAML (or BAML), the XamlReader deserializes all of the XAML's contents. Every XAML element it finds creates an instance of an object - so the Style elements under the UserControl.Resources element generate Style objects that get added to the user control's resource dictionary at the time the object is deserialized. (It's actually a little more complicated than this, since there are apparently parts of XAML deserialization that are asynchronous, but it's close enough for the purposes of this discussion.)
It's important to understand that Resources is not a static property. Every instance of a user control has its own resource dictionary. If you put 300 styles in the user control's XAML, and you create 100 user controls, you'll be creating 30,000 Style objects. This is true whether you're using merged dictionaries or not.
If your resource dictionary is as huge as you say, by far the best thing to do is to put it into the application's Resources property. That way you only pay the price of deserializing each object once.
Related
I'm kind of a beginner with the WPF platform. I've done a few Windows Forms apps that were very basic and now I'm working on a much more complex app for my current work.
I'd like to implement an MVVM model, but I'm getting lost in the different articles on how to do so.
Here's a screenshot of the app interface:
The section on the left is a ListView containing 6 sections that correspond to different UserControl. I would like the section on the right to display the UserControl that corresponds to the selected Item.
Each UserControl is stored in a separate XAML file.
By looking online, I found that I should use a ContentControl in my MainWindow, but every attempt I've made has been unfruitful. I know there's more than one way to skin a cat.
Which method would you use? Do you have any concrete examples or sources where I can find how to make it work?
The only difference between UserControl and ContentControl is the OnCreateAutomationPeer method. This method is responsible for UI automation.
Although this method is rarely used in practice, it is customary to use UserControl to represent some complex data types.
A typical use for a UserControl is to retrieve data (in normal CLR types) through the data context.
And the Content property specifies (using XAML) a visual tree to represent that context.
And each such UserControl is declared as a derived type (just like a Window).
If necessary, additional properties (CLR and DP) and other members (event handler methods, for example) are added to such a UserControl.
The base class ContentControl itself and others of its successor are used somewhat differently.
The data in them goes directly to the Content property.
And their visualization is set by the data template in the ContentTemplate property.
While DataTemplate's can be quite complex, they are usually much simpler than the XAML markup of the UserControl.
And, besides the task of visualization, you cannot add additional logic (properties, fields, methods).
Here's a photo of the app interface: ...
In this UI, I don't see where the ContentControl can be applied.
On the left is a navigation bar consisting of buttons.
It is usually implemented directly in the Window from an ItemsControl or ListBox.
On the right (while an empty area) is the region for the page content.
Usually, when you click on a button in the navigation bar, the corresponding UserControl is set to this region.
At a lower level, deeper in the visual tree, for smaller elements, it is quite possible that a ContentControl is needed.
P.S. Just in case, I will clarify, in view of the comment below.
By area for pages, I do not in any way mean the use of Frame + Page.
This is a very specific pair and it is extremely rarely justified to use it.
In combination with MVVM, its use is even more difficult, since this pair does not support DataContext inheritance.
And this is the main way for the View to interact with the ViewModel.
We're using ResourceDictionaries to store layout information for our app. The lazy initialisation is great because we can grab the required layout for an element only when that element is created. The problem is that each element gets the same instance from the ResourceDictionary for each one that shares the layout (or the same one if it goes out of scope and is needed later).
We could store templates in the dictionary then it doesn't matter if they're shared but we have quite a nice system going if it wasn't for this caching behaviour.
Is there a way to change this behaviour of the dictionary or am I going to have to write my own class which creates items from the XAML on demand?
Try applying x:Shared="false" attribute. Each resource should then get seperate copy.
I have started using xaml based icons in my WPF app, but am struggling to find a simple way to store and share them. The icons are DrawingBrushes.
Do I?
A) Store each icon in its own xaml file wrapped in a resource dictionary. This means that I either have to pull in each icon resource every time I want to paint one, or create a standard "icons" dictionary that pulls every xaml file. This seems a pain to have to maintain, and I still have to pull in the icons resource dictionary every time I want to use an icon.
If I did go for this, how do people normally display the icon? Just a Canvas with the brush as the background?
B) Store each icon in its own xaml file as a UserControl. This makes displaying an icon dead easy - just plonk the approprate control in, and its arguably simpler to declare the XML icons namespace at the top of your XAML rather than merging a resource dictionary.
C) Store all icons in one XAML file wrapped in a resource dictionary. One dictionary to merge but without the maintenance of pulling in individual files into that dictionary. Potentially awkward to edit icons though.
D) ....?
How are other people managing their icons?
Is there a way to pass parameters to a resource dictionary? I think that I can attach a code behind for the purpose of specifying event handlers, but unfortunately, I also need to access a reference to the parent control from the event handlers. The codebehind, I believe, can be attached by specifying an x:Class attribute for the resource dictionary in xaml, and then creating a class in the same folder, the filename for which is something like [resource dictionary name].xaml.cs.
The purpose is to seperate the code for four hierarchical data templates that I'm using in a single treeview control. The xaml for the treeview is getting a bit long and ugly to look at, so I was hoping to break it down into four resource dictionaries. Any thoughts are welcome!
Andrew
You know you can merge your Resource Dictionaries and then reference the DataTemplate within those dictionaries as needed within the TreeView.
Resource dictionaries sound like a slightly peculiar way to do this. Resource dictionaries are all about sharing instances - they let you use a single instance of something (e.g. a style, a template, a brush, or whatever) from multiple places. They're not really a mechanism for dividing your UI up to simplify individual Xaml files.
The usual mechanism for splitting overly complicated Xaml files up into a few, more manageable smaller files is the user control. (Resource dictionary merging comes into play when you already have a resource dictionary, and it's got too big. But you wouldn't normally introduce a resource dictionary just to start splitting things up. On the contrary, resource dictionaries tend to encourage overly large Xaml files, which is why dictionary merging had to be invented in the first place!)
Most of the time, when I define a data template, I make it contain nothing but a single user control. And if that becomes more complex, I'd split that user control up into more user controls.
From your description, it sounds like your Xaml file has become large because you've got four large hierarchical data templates in there. If you took the body of each template and turned it into a user control, your four templates would now become very simple - something like this:
<HierarchicalDataTemplate x:Key="t1" ItemsSource="{Binding Path=Children}">
<loc:TreeItemTypeOne />
</HierarchicalDataTemplate>
and you'd most likely no longer need to put those templates into separate files. But because the guts of each template is now in a user control, that gives you a place to put your codebehind.
You mention needing a reference to the parent control. That worries me - it makes it sound like you have too much code in your codebehind. But one thing at a time... You could solve that problem by defining a dependency property called ParentControl on your user control, and then put this in the template:
<loc:TreeItemTypeOne
ParentControl="{Binding RelativeSource=
{RelativeSource AncestorType=loc:ParentControlType}}" />
But frankly, as soon as I find myself in a position where I need this, I ask myself: how did I get myself into a position where that seemed necessary, and what can I do to fix that?
I've spent hours working on an application design in WPF and created a whole bunch of different styles along the way. But I noticed that I actually had just edited the styles in the SimpleStyles.xaml file and not a custom dictionary.
So, I started right clicking all controls I could find and selected "edit a copy" and created a copy in a custom resource dictionary. But then I found that alot of the controls are based on several styles. SimpleScrollViewer e.g contains both the thumb and probably more. This created a huge mess in the overall structure of styles in the entire project.
And thus, my question is as follows;
What should I think about when doing this project from scratch again?
Is it best to edit a copy of the SimpleStyles controls? Is there a tool of some sort to manage stuff like this?
Expression Blend will add a resource dictionary for the Simple Styles the first time you use a SimpleStyled control. For real world projects it is best practice to separate resource dictionaries by resource type and then functional area.
For example you will have horizontal resource dictionaries that fall into the following categories:
Brushes
Control Styles
Converters / Selectors
Since these are horizontal their filenames are pretty self-explanatory (e.g. Brushes.xaml, ControlStyles.xaml, Converters.xaml, etc.)
If you are using Silverlight you should probably think about using Themes. In which case you would create Brushes.xaml and ControlStyles.xaml for each [themeName]\generic.xaml you create.
Then you should create resource dictionaries for functional areas that will house the following things:
Item Templates for various ItemsControls used.
Content Templates for various ContentControls used.
One off Control Styles
Each functional area would have a resource dictionary that had the above items (e.g. CustomerManagementStyles.xaml, Orderingstyles.xaml, etc.)