In NetFramework I was able to apply WPF implicit styles to a target control type by placing the styles in a ResourceDictionary, and referring to that in app.xaml.
Now that I am moving my applications to .NET6 I have found that the styles defined in a resourcedictionary are not being applied. However, if I define them in the <Window.Resources> they are applied. No doubt they would be in Application.Resources in app.xaml.
Has Microsoft made an obscure change in .NET6 that would cause this problem, or am I missing something? (I have placed the dummy string"<clr:String x:Key="DummyString">Dummy</clr:String>" in the ResourceDictionary as advised by someone.
Any help would be appreciated, as this problem is not only going to make my ResourceDictionaries obsolete, but will increase the length of my code in the .xaml file, and I will have to repeat that code in each window instead of just importing a ResourceDictionary to each project.
Related
I'm struggling with Templates in WPF
I understand the concept in that I can have a control, and 'override' the ContentTemplate (or similar). I use it often with the TabControl
However, I don't understand it in terms of what the initial control looked like. And if we are limited on the names. EG, could we build a control and overwrite the NonsenseNameTemplate?
If I were to build my own UserControl and provide the ability for people to override things like my NonsenseNameTemplate, what would this code look like?
My guess, with pseudo code would be
<UserControl>
<NonsenseNameTempalte>
//some resources
//some other controls
</NonsenseNameTempalte>
</UserControl>
In the above example, I can fully understand how I could create a new control and overwrite the NonsenseNameTemplate but I can't see any code examples of the UserControl and it's usage.
Template is nothing more than a (dependency) property. By writing
<Button>
<Button.Template>
<ControlTemplate>
...
</ControlTemplate>
</Button.Template>
</Button>y
you are doing nothing more than creating a new instance of ControlTemplate class and assigning it to Button.Template property of that specific button. Each control has it's own ControlTemplate saved somewhere in it's assembly. It is generally not so simple to actually get those default templates, but Blend can help with it.
Of course, you can create your won NonsenseNameTemplate property, but actually using it would require some deep knowledge of WPF composition, layouting and rendering. Which is usually not required for normal usage of WPF. And I agree that there is not a much online resources about doing something like this, for exactly this reason.
I too had an early on learning of Templates. I posted a step-by-step answer to another question via a customized button control. The nice thing about that sample, you can build and play with styles and templates in a small project and see visual impact without requiring full project rebuild
To start with, as you have mentioned that you do not have Blend. You can have Blend and install it with Visual Studio 2013 Community.
You can download this here if you do not have it already.
http://www.visualstudio.com/products/visual-studio-community-vs
A part of the installation process, it allows you to select and install Blend. Also, the newer editions of visual studio give you some of the power of blend. In your design view you can right click on a control and create or copy a template.
On to the question.
As Euphoric has mentioned. Custom control authoring does require a little more in-depth knowledge of WPF, or any of the XAML frameworks. However, there are Visual Studio templates that can help you in the right direction.
As for the template naming, you have three types of templates you will come across in XAML. ControlTemplate (which for your purposes is the one we are interested in), ItemsPanelTemplate and DataTemplate. Again, as Euphoric has said, there are few circumstances where deriving a custom version of any of these three templates would bring anything to the table.
If you were to create a test WPF application, once you have created the basic project and solution. Go a head and add in another project, and from the templates VS provides, File -> Project -> New -> Windows Desktop. In the project template list, find 'WPF Custom Control Library'. Once created, reference this project in your main WPF project.
This custom control library project will give you a skeleton setup for what you are looking for.
If you look in this project here are some things for you to note.
Firsty, you will find a folder called Themes and in there a file named Generic.xaml. In there you will see a style that has a setter setting the Template property. You will also see that both the Style and set ControlTemplate have a set TargetType that should be local:CustomControl1.
This is important as this is showing you how to create a custom controls default template. Now, to apply this template look in CustomControl1.cs and consider the following code.
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
For this control named CustomControl1, that template we looked at in the xaml will be automatically set as that controls default template where ever that control is used.
This project is a good starting point. But now you may want to override this ControlTemplate inside your main project. This is simple. I have code that looks something like this inside my main WPF project.
At the top of the MainWindow.xaml
<Window x:Class="CustomControlTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CustomControl="clr-namespace:CustomControlTesting.CustomControlLibrary;assembly=CustomControlTesting.CustomControlLibrary"
Title="MainWindow" Height="350" Width="525">
And in the body,
<CustomControl:CustomControl1>
<CustomControl:CustomControl1.Template>
<ControlTemplate TargetType="{x:Type CustomControl:CustomControl1}">
<Grid>
<!-- Define my look to override the template -->
</Grid>
</ControlTemplate>
</CustomControl:CustomControl1.Template>
</CustomControl:CustomControl1>
This is a brief overview and certainly misses out a lot. But I hope this is of help to you and can get you started.
I am trying to use a ResourceDictionary in loose XAML and load it a runtime to provide templates and styles to a WPF app. I have the XAML available in a local directory and am adding a new ResourceDictionary to App.Current.Resources.MergedDictionaries in app startup using a URI.
When the XAML goes to parse, it blows up on a template where the TargetType is a custom control from the assembly that is consuming it.
The specific message is:
'Failed to create a 'Type' from the text 'controls:CustomType'.'
I already have the namespace mapped in the ResourceDictionary at the top:
xmlns:controls="clr-namespace:TEST.UI.WPF.Common.Controls"
There are articles out there stating that loading ResourceDictionaries from loose XAML is possible but none of them that I have found address custom types within those loose XAML files.
Any help is appreciated!
Since you are loading this at runtime and it is not built within the project then the ResourceDictionary does not know of your assembly. You will have to include the assembly in the namespace for it to be recognised.
xmlns:controls="clr-namespace:TEST.UI.WPF.Common.Controls;assembly=Common"
You should be able to run you app after you add ';assembly=yourAssembly' to the namespace declaration.
I'm having some issues with resource files in my modular application.
I have Infrastructure.DLL and some custom controls inside this DLL. Those controls using templates from themes/generic.xaml
Issue that I have - Blend doesn't recognize those resources. Visual studio does.
Ideally I'd like to have styles for my cusom controls inside generic.xaml and styles for other controls somewhere else in common library that I can reference from my modules.
I also need Expression Blend and VS to work properly.
How do I arrange solution to make it happen?
PS. Important! WPF is different but I'm interested in Silverlight solution
You just need to create design time resource for your generic.xaml in order to let Blend recoganize it. Take a look at this post.
In each of your modules, you create a ResourceDictionary like this.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
Source="/xxx.Silverlight.Controls;component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Also, in your .csproj file, you need to add this. Please note that normally this piece of code is auto-generated by Blend, so if your ResourceDictionary is auto-generated, you don't need to do the following.
<Page Include="Design\DesignTimeResources.xaml" Condition="'$(DesignTime)'=='true' OR ('$(SolutionPath)'!='' AND Exists('$(SolutionPath)') AND '$(BuildingInsideVisualStudio)'!='true' AND '$(BuildingInsideExpressionBlend)'!='true')">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<ContainsDesignTimeResources>true</ContainsDesignTimeResources>
</Page>
Design is the folder I created for storing my DesignTimeResources.xaml. I pretty much have the same structure as yours. :)
I'm writing some extension modules for a WPF Composite application supplied by another vendor. The application is themed, and gives users the option to select from a number of themes which will change the appearance of the entire applications, including any custom modules that register themselves with the theme manager appropriately.
I really want my custom extensions to look like an integrated component, so I'm trying to use only styles defined as resources within the main application. As I'm still learning the nuances of XAML, I'm styling more by trial and error.
I'm wondering if there's a way of 'discovering' what styles are available in a different assembly. Here is an example of what I'm currently doing.
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<common:DesignTimeResourceDictionary Source="/Vendor.Desktop.WPFCommon;component/themes/generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Border
Background="{DynamicResource LightGradientBackgroundBrush}"
Margin="0"
>
The LightGradientBackgroundBrush is defined in the vendors assemblies. By including the above ResourceDictionary, the style is present during design time, and the brush isn't underlined in the XAML editor.
Can I find what other styles are defined? I'm only aware of that style because it was mentioned in passing in a sample provided by the vendor.
Edit:
I'm aware of a BAML add-in for reflector, but it doesn't work with reflector 7 unless it has been recompiled/patched. Someone has already done that here though.
I was hoping there was a better solution though. Intellisense for styles would be great.
There used to be a Reflector add-in for viewing BAML resources that worked well for that. But I haven't used Reflector in a while since Redgate crashed the party. It may not work with the current version.
You know where your resource dictionary is so you should be able to load it up in code and enumerate over the available resources. This will at least give you an idea of what's available.
See this link: http://blogs.claritycon.com/leeroth/2009/05/20/load-xaml-resource-dictionaries-at-runtime/
Enumerate over the Keys property and use the item property to access the resources. You can get as detailed as you want, but at the very least you should be able to spit out the resource names.
I have multiple silverlight project that I would like to use the same styles, colour scheme, and some templated objects.
How do I accomplish this?
One way to do this would be to create a new silverlight class library which would be your shared theme/style assembly which would be referenced by the other silverlight projects. This assembly would have one or more Resource Dictionary XAML files in it which could define all of your styles, brushes and templates. You could even set up some cascading style hierarchies using the BasedOn attribute of the Style class.
You could then use MergedDictionaries to merge these styles into your application either at the App.xaml-level or on a page-level basis.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/SharedThemeAssembly;component/MyStyles.xaml"/>
...other ResourceDictionaries to merge in...
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
You would then reference the shared styles / brushes as you normally would any other StaticResource.
There are two options, first as Dan indicates you could create a library that is shared by the other projects. If the clients access several of your projects and your projects use application library caching then you reduce the total download size.
The other approach is to create a Resource dictionary in one project, then add the same file to the other projects. Note in the Add Existing Item dialog the add button has a small drop down image, drop it down and then select "Add as Link".
This leaves the dicitionary as a simple Xaml file. One advantage I can see for this is to actually leave the dictionary file out of the Xap and just place it in the clientBin folder (or whatever the folder that the Xap is placed in). This approach allows all the Xaps to share the single dictionary (in the same way the first approach does) but allows the Xaml to be tweaked without messy rebuilds.