Right now in our application, which has many modules/projects in the solution, we have a specific project to hold resources called "Resource.Dictionaries", and inside that project are individual ResourceDictionary XAML files for each and every style we make.
Then, for each instance where we need one of these styles, we call it inside the resources property of the topmost parent in each view/usercontrol/data template or in c# if it's a custom control.
In short, my question is this; does putting all of our styles and other resources in the app.xaml slow anything down (even if app.xaml just becomes one big merged dictionary pointing towards our remote Resource.Dictionaries), or is it best to continue referencing the styles/other resources ONLY where and when they're needed.
Related
I have an WPF Application here which is in the MVVM Pattern using MVVMLight as Framework and a MEF Plugin with a UserControl named VCNEditor.
The Main Application uses an Attached Behaviour named DialogViewModel of Type DialogBehavior to display Dialogboxes. The DialogBehavior takes care of binding the view to its pre-created DialogViewModel : IDialogViewModel (viewmodel first) by using:
var resource = Application.Current.TryFindResource(viewModel.GetType());
The Plugin is a Library with a UserControl. The UserControl is Lazy loaded dynamically from an "Extensions" directory and only visible if present.
That works so far. The Problem i currently facing is: I tried to Display Dialogboxes within my Plugin in the same way i do within the Main Application.
Meaning: I defined a Property Named "Dialogs" of Type
ObservableCollection<IDialogViewModel>
in my UserControlViewModel : IDialogViewModel and DataBind that Property to my Attached Behavior.
When i now Add a new DialogViewModel to that collection
Application.Current.TryFindResource(viewModel.GetType())
is not able to find any resource because Application.Current is returning the Main Application and the library doesnt have any resource dictionary like in app.xaml in the main application.
I cannot add resources for the dialogs of the plugin to the Main Application because this will break my loosely coupled plugin architecture.
I am just a casual-developer and it would be nice if someone could point me in the right direction.
The current workaround is, that i create the view "by hand" in every viewmodels construcor. But i think that this doenst look very well.
Thank you for your Support.
If i understand you correctly, you can easily add your plugin styles and resources to the Application.Current.Resources in code.
One way to solve this will be to create a merged Dictionary architecture for your plugins. On your MEF plugin Interface implement a HasResource bool Property, and ResourceDictionary/ResourceDictionaries Property.
When you plugin loads, simply check for those properties and if has resources just add them to the host application via
Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary);
Additional Resources
Application.Resources Property
Gets or sets a collection of application-scope resources, such as
styles and brushes.
ResourceDictionary.MergedDictionaries Property
Gets a collection of the ResourceDictionary dictionaries that
constitute the various resource dictionaries in the merged
dictionaries.
ResourceDictionary Class
Provides a hash table / dictionary implementation that contains WPF
resources used by components and other elements of a WPF application.
In my project I have implemented this plugin manager:
https://code.msdn.microsoft.com/windowsdesktop/Creating-a-simple-plugin-b6174b62
In this way I can add .DLL file and make my project more modular.
I wanna know if in one of these .DLL plugin I can add a .xaml with user interface, and use it inside my main project to visualize the content of that xaml in my main GUI.
In this way I can make my app more modular not only by code library but also with user interface.
Thanks
If you create a project that contains WPF UserControl items, then as long as you expose those items through the DLL interface then you can utilise them in another project.
You should be able to verify this very easily by doing something like the following:
1) Within your 'DLL' project make a public class SquareControl, which is simply a UserControl under the hood, and specifically a canvas containing a red square of a fixed size.
2) Within your utilising project, reference the DLL.
3) Within your utilising project, in C# code somewhere create an instance of SquareControl, and check in the debugger that its properties are as you expect.
4) Then create a UserControl within your utilising project, and open VS Designer for that control. Within the empty Grid that has been created for you drop an instance of SquareControl, and you should be able to see this within Designer. Getting your xaml namespace definitions can be awkward the first time around but there's plenty of help available for that. Then fire up the application and see it there.
I have started using WPF and started with some games and visual apps.
In my first App I started a blank project then made a class that inherited from a window which had a canvas that I added and removed images from Dynamically, like follows:
class MainWindow : Window
{
public Canvas canvas=new Canvas();
public MainWindow()
{
this.addChild(canvas);
}
//add an image every second move it and remove it
}
This would be impossible with static XML but someone told me it is a bad idea to do controls dynamically, is it true?
Is it a performance loss?
And is there a simple and efficient method to draw, lets say, 100 images at a 30 fps without lag?
There is no performance loss / the performance loss is negligible compared to the HUGE productivity / code cleanliness gained by doing things the RIGHT way.
And XAML is not static.
There is DataBinding, and if you need to add / remove items dynamically there is the ItemsControl.
There is also the concept of DataTemplates that dynamically render specific UI depending on what Model / ViewModel objects are passed to it.
Do not manipulate nor create UI elements in procedural code. WPF is not winforms.
None of the controls are reallystatic. There is no any runtime difference.
Most likely, by using XML you meant XAML. XAML merely serves as a data source use to actually generate C# code (or the code in VB.NET or other .NET language) to compile is and to use exactly in the same was as you would do it programmatically.
You can use this fact in your work. If you know how to do certain things with XAML but don't know how to do similar thing in C# code, do the following: develop XAML-based project and build it. Then perform the search for *.cs files under the directory where your project file is located. You will find some *.cs files which was not in your source code. Those files were auto-generated with the use of XAML. Look at them.
You will be able to learn how it works behind the hood.
Good luck,
I have the following:
MainApp
- Assembly 1 (Contains UserContolA)
- Assembly 2 (Contains UserControlB)
- Etc.
Not every Assembly will be loaded though, so
Neither assembly can compile if I try to assign resources to controls (button, combobox, etc.) that it can't find because I want my MainApp to dictate those resources. But, if I include the resources in the assemblies it seems that I can't override them (because WPF goes from bottom-up for resources giving prioroty to those closest to the bottom).
Also, I'm afraid even if I do solve this problem trying to get it to be dynamic in a way that a user can select from different "themes" that it'd make it even more difficult.
I included prism in the topic because I plan to use that as my framework, but haven't looked deep enough into it to see if it affects this in any way or has something built into it already, which would be a Godsave.
Really what you are asking is what is the best approach to splitting up a WPF application into multiple assemblies. Your strategy is to create reusable control libraries and let the app integrate everything. Great so far. The last issue you need to address is resources. To handle that you need to add a Themes\Generic.xaml and move all the resources in your library into it. Then the library can find all the resources it needs and the application can override it if it so wishes.
Here is a good article that discusses some of the issues related to resources across multiple assemblies:
Control Authoring Overview
Also be sure to set up your control assembly attributes so that Generic.xaml will be searched:
[assembly: ThemeInfo(
ResourceDictionaryLocation.None,
ResourceDictionaryLocation.SourceAssembly)]
Edit:
The above solution applies to custom controls, not to UserControl resources. To handle UserControl resources in a separate assembly that the main application can override, you can use this approach:
Use {DynamicResource ...} and simply leave the resource definition out of the UserControl.
The problem with this is that although the resource will be located correctly at run-time, it won't be found during design-time and this can make your UserControl very hard to work with. There are two workarounds for this problem:
Use Expression Blend together with its "Design Time Resources" feature. Simply opening a project that has resources that cannot be resolved will cause Blend to prompt you for which resources to use at design-time.
Use Visual Studio to design your UserControl and include design time resources in the XAML itself.
For Visual Studio you can include this in your UserControl while designing it only:
<UserControl.Resources>
<ResourceDictionary Source="/YourControlLibrary;component/DesignTimeResources.xaml"/>
</UserControl.Resources>
Once you are done designing it, simply comment out that code in the XAML. It's inconvenient, but until Visual Studio supports design time resources, at least it works.
We have a C# solution that is based on loose Xaml (or Hosted Xaml - have never been to sure of the correct term!). But basically we take a Xaml file and load it into a XamlReader and then pop that FrameworkElement onto a UserControl. We require the ability to handle data binding and we have a ViewModel that takes care of this. However, although I can inject the DataContext through code by setting it on the newly created FrameworkElement, if I want to work easy through Blend and use the built in list of bindable properties when you select the 'Data Binding..." option on a property I need to have set the DataContext right there in the Xaml (if not Blend will add it to the Xaml). I'd rather not have to do this because as I say I am doing this through code already.
The question is - Is there any way to avoid this?
I was thinking of doing this somehow through the app.xaml but the problem is depending on the screen and when it is shown it will have a different context (so we dynamically change the context) and I'm pretty sure you can't load in multiple data contexts.
Maybe there's a better way of splitting this up. Our solution has the following: -
A WPF application with a MainWindow.xaml (the main application)
A User Control in a separate assembly that is placed on the MainWindow.xaml by the main WPF application (above)
This User Control is then bound to the View Model
The main application sets the DataContext as it goes through it's build in state machine.
All Loose Xaml files are held in the main application.
So basically depending on when the state machine displays a screen it will have a different Data Context. The State Machine handles pushing the Data Context and those screens will only work if they are used in the correct context. So we don't really need (or want) to have to set the data context in the Xaml. It done by the state machine.
But I haven't been able to find much info on the Tinterweb around Loose Xaml so we're pretty much learning as we go...
Thanks in advance!
Have you tried d:DataContext={d:DesignInstance ...} ?
It allows you to define a DataContext for design time only, for Blend and VS.