What does the <vm:SimpleViewModel x:Key="viewModel"/> mean in WPF? - wpf

I am new to WPF and MVVM, actually started just a week back and I am trying to code up an application using both WPF and MVVM, while coding up an example I came across the following statement <vm:SimpleViewModel x:Key="viewModel"/> and I am trying to reason about it. I understand what 'x:' refers to, its the default XAML namespace mentioned in the XAML file and I have created a namespace for my own ViewModel class that the UI will be interacting with and I have given it an alias "vm" and SimpleViewModel is the ViewModel for my application, the statement for the purposes of reference is xmlns:vm="clr-namespace:MVVM_Tutorial".
My Reasoning for the statement <vm:SimpleViewModel x:Key="viewModel"/> is that a Window is a XAML element and has a resource dictionary that it refers to resolve and refer to certain elements, hence inside its resource dictionary which is defined in the "x:" namespace we are assigning a variable called "Key" whose value is the SimpleViewModel class defined in the "vm:" namespace. Just want to know if I am right with my reasoning or is there something that I am missing and would want to know proceeding further from here.

XAML is just markup that describes an object graph. Code is also markup that describes an object graph. I can say this
var window = new Window();
window.DataContext = new MyNamespace.MyViewModel();
or I can write the exact same thing like this
<Window xmlns:blahblah="clr-namespace:Normal.Xmlns.Deleted.For.Brevity"
xmlns:this="clr-namespace:MyNamespace">
<Window.DataContext>
<this:MyViewModel />
<!-- snip -->
Any object that can be instantiated in code can be used in xaml. There are some restrictions (e.g., default public constructor without arguments), but for the most part this is true. XAML just defines an object graph that is deserialized at runtime.
Since any type can be referred to in xaml, you could, hypothetically, have moved that instance of MyViewModel to a resource dictionary and referred to it via a StaticResource or a DynamicResource. Note, anything you put in a resource dictionary has to have a key, assigned via x:Key:
<Window xmlns:blahblah="clr-namespace:Normal.Xmlns.Deleted.For.Brevity"
xmlns:this="clr-namespace:MyNamespace"
DataContext="{DynamicResource lolderp}">
<Window.Resources>
<this:MyViewModel x:Key="lolderp" />
<!-- snip -->
XAML is a subset of XML, and uses XML namespaces to map to code namespaces in the current, or other, assemblies. It's how the framework knows what object MyViewModel refers to. To learn more, read this link on msdn.

I'm sure someone else can chime in with more clarification...
In the xaml file, the references of
"xmlns:[something]="clr-namespace:[yourProjectOrLibrary]".
Since your code-behind can be verbose with long name space references, and your SOLUTION may be made up of multiple projects (such as different DLLs), when the XAML is processed, it uses the "xmlns" as a reference to whatever "yourProjectOrLibrary" is... In your case the project/class "MVVM_Tutorial".
Now, the "vm". This is just an "alias" within the xaml, so anytime it is referencing a
The xaml knows where it originates to get resolution to control, properties, types, etc.
As for the "x:Key" part... Not positive, but when I was first building out my customized themes, also ran into confusion about the x:Key. My interpretation of this was found to be x:Key is like a private reference, but by being given the name ..x:Key="viewModel"... is making this "name" available later within the xaml file.
This "key" can then be referenced later in the xaml... For example,
<ControlTemplate x:Key="CTButton" TargetType="{x:Type Button}" >
<!-- Start border of button to have a rounded corners -->
</ControlTemplate>
Then later within the theme, I could reference this "Key"... in my case "CTButton". So if I wanted multiple controls to use / derive from same control template, I could have them reference it...
<someControl>
<Style>
<Setter Property="Template" Value="{StaticResource CTButton}" />
</Style>
</someControl
Again, I don't get EVERYTHING about all the xaml markup, but hopefully clarifies this for you some.

Related

What is the meaning of x:Name in xaml (WPF) and its use with Storyboard

<Border Name="ItemBorder" Margin="5 5 0 5" BorderBrush="Black" BorderThickness="1" Height="75" Width="75">
<Border.Background>
<SolidColorBrush x:Name="ItemBorderBrush" Color="LightBlue"/>
</Border.Background>
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="someEvent">
<BeginStoryboard>
<Storyboard TargetName="ItemBorderBrush" TargetProperty="Color" Duration="0:0:1" >
<!--Storyboard TargetName="ItemBorder" TargetProperty="Background.Color" Duration="0:0:1"> -->
<ColorAnimation To="White"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
I'll try to explain my question clearly. The Storyboard Target name, when it is "ItemBorder" (the commented out line) works intermittently. Sometimes I get an error that the name "ItemBorder" cannot be found in the scope.
I decided to follow a style from an MSDN example of this, and change the color property directly on the brush, instead of having the target of the storyboard be the border, and changing the color of the border's brush by property (the commented out line). This seems to work.
However, Name="ItemBorderBrush" does not compile because Name is not a property of SolidColorBrush so I use x:Name="ItemBorderBrush" Both Name and x:Name are accepted for the Border. Why is this?
What does the x: mean (how is x:Name different from Name), and why would having the Name property of border only work with the storyboard sometimes?
The x: prefix is simply setting an attribute from a seperate namespace:
Within the namespace declarations in
the root tag of many XAML files, you
will see that there are typically two
XML namespace declarations. The first
declaration maps the overall WPF
client / framework XAML namespace as
the default:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
The second declaration maps a separate
XAML namespace, mapping it (typically)
to the x: prefix.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
The relationship between these
declarations is that the x: prefix
mapping supports the intrinsics that
are part of the XAML language
definition, and WPF is one
implementation that uses XAML as a
language and defines a vocabulary of
its objects for XAML. Because the WPF
vocabulary's usages will be far more
common than the XAML intrinsics
usages, the WPF vocabulary is mapped
as the default
So, the reason that Name and x:Name both work on Border is because Border has a property called Name. It also supports the XAML Intrinsic usage of x:Name (which is what WPF uses to create the named instance of the class).
However, SolidColorBrush doesn't have the property called Name so it only supports the XAML Intrinsic usage of x:Name.
There really is only one name in XAML, the x:Name. A framework, such as WPF, can optionally map one of its properties to XAML's x:Name by using the RuntimeNamePropertyAttribute on the class that designates one of the classes properties as mapping to the x:Name attribute of XAML.
The reason this was done was to allow for frameworks that already have a concept of "Name" at runtime, such as WPF. In WPF, for example, FrameworkElement introduces a Name property.
In general, a class does not need to store the name for x:Name to be useable. All x:Name means to XAML is generate a field to store the value in the code behind class. What the runtime does with that mapping is framework dependent.
So, why are there two ways to do the same thing? The simple answer because there are two concepts mapped onto one property. WPF wants the name of an element preserved at runtime (which is usable through Bind, among other things) and XAML needs to know what elements you want to be accessible by fields in the code behind class. WPF ties these two together by marking the Name property as an alias of x:Name.
In the future, XAML will have more uses for x:Name, such as allowing you to set properties by referring to other objects by name, but in 3.5 and prior, it is only used to create fields.
Whether you should use one or the other is really a style question, not a technical one. I will leave that to others for a recommendation.
See also AutomationProperties.Name VS x:Name, AutomationProperties.Name is used by accessibility tools and some testing tools.
refer In WPF, what are the differences between the x:Name and Name attributes?

Beginner - confused about binding and resources in WPF

I'm trying to learn WPF but I find it very difficult to understand bindings, the "resources" thing, and object creation.
My background is in C++/MFC and C#-Winforms.
My questions:
Most of the examples I see in XAML (in MSDN and in two other WPF books I've read) use StaticResource in the binding expression. Are these related in any way to static members? Or is this just a misleading name? When a reference is made to any object as a StaticResource, when is it instantiated?
As far as I can see StaticResources are used with "things" defined in the "Resources" section of the app/window/control etc.
Now, these Resources sections are very confusing to me.
What exactly are they? From my experience in MFC these were icons, strings, etc. However, judging by all the examples I've seen, in WPF these seem to be essentially a "dumping ground" for
(a) all kinds of global object definitions in markup (styles, data templates, etc)
(b) all kinds of global object instantiations in markup
Am I correct? This strikes me as very messy.
It essentially involves learning all sorts of semi-DSLs in XAML (for defining styles, for defining data templates, for creating objects etc), and sticking them together in the same place.
I keep thinking about something like editing the resource file (.rc) in MFC by hand. At least there the sections were well separated and the syntax for each resource was relatively simple.
To tie up the previous two questions: When I define an object instance in the Resources section, and later reference it from a StaticResource binding, when exactly is it instantiated?
MSDN says (in "How to: Make Data Available for Binding in XAML"):
one way you can make the object
available for binding is to define it
as a resource
However, this isn't very clear. What do they mean available? Do they mean created? Do they mean hooked up to the binding subsystem? And when exactly is that object created?
From playing around with a simple example I saw that WPF seems to create this object for me when it tries to attach the binding. And this is even more confusing.
EDIT:
After the clarification by karmicpuppet below, I'm still confused as to how this is connected to Binding.
Suppose I have in my resources:
<local:Person x:Key="MyPerson" Name="Title"/>
(where Person is a class with a property called Name) and then in the window I have:
<TextBlock Text="{Binding Source={StaticResource MyPerson}, Path=Name}"/>
1) What does this do? Does it goes through the same steps - searching for the resource and then applying it to the Text property? Does the MyPerson object gets created at the time of Window creation, or later?
2) Do I have to use the Binding mechanism to bind to the Name property? Can't I bind to it directly like you did above with myBrush? Why can't I do something like this?
<TextBlock Text="{StaticResource MyPerson, Path=Name}"/>
Is it just a short-sightedness on the part of the framework? I think I'm missing very big here, but I can't seem to understand what...
3) I tried using DynamicResource, but I am very confused about each step I took.
a) Added a DependencyObject with a DependencyProperty above my single Window class in code (is this DependencyObject necessary?)
public class SomeText : DependencyObject
{
public string Header
{
get { return (string)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string), typeof(SomeText), new UIPropertyMetadata(0));
}
b) Added an instance of it to the Windows.Resources (is this necessary with DynamicResource? MSDN seems to say no, but if so I can't figure out how to do the next step in XAML)
c) I tried both:
Text="{Binding Source={DynamicResource HeaderText}, Path=Header}"
Which gave me an exception, and
Text="{DynamicResource HeaderText}"
But I couldn't understand where to put the path to the Header property.
This is my 5th or so attempt to fiddle around with WPF lately, and each time I get stumped by this seemingly simple things which don't work. I've read 2 books and I really try to understand the MSDN articles, however they're of no help at all.
First, an overall comment:
WPF is hard to learn. It's hard to learn because there are several different fundamentally new concepts that you have to get your head around at the same time. The struggle that you're having right now is that you're trying to learn at least three different things at once:
How the XamlReader (and particularly markup extensions) deserializes XAML into objects.
How the FrameworkElement's resource dictionaries work.
How data binding works.
Something like this:
<TextBox Text="{Binding Source={StaticResource MyPerson}, Path=Name}"/>
is engaging (at least) three very different technologies at the same time. Those technologies are all designed to be as flexible as possible, which only makes them more confusing to the beginner. The idea that a binding source can be just about anything: that's hard to grasp. The idea that a markup extension is a special kind of serialization format that supports recursion: simple enough to understand in principle, but a little baffling when you first start working with real-world examples. The idea that a resource dictionary can contain just about anything, and that the resource searching algorithm essentially makes resources inheritable: again, pretty simple in concept, but easy to lose the thread of when you're trying to figure out data binding and XAML at the same time.
It's frustrating, because something that's conceptually simple - "I want to bind this control to a property of an object that I've created" - requires that you understand a great many things before you can actually express it in XAML.
The only solution is to be patient, and to make sure you understand things at the lowest level possible. When you see this:
{StaticResource MyPerson}
you should be able to think, "That's going to invoke the StaticResource markup extension handler, which retrieves an object from a resource dictionary using the key MyPerson when the XAML is deserialized.
It's extremely challenging at first. I've been developing software professionally for 35 years, and I've found WPF to be the most challenging technology platform that I've ever learned by a considerable margin. But all of this stuff is hard to learn because it's incredibly functional and flexible. And the payoff of learning it is huge.
To address a couple of issues that karmicpuppet didn't:
From my experience in MFC [resources] were icons, strings, etc.
That hasn't changed. You can still create resource files in WPF and load them into objects at runtime. There are lots of different ways of doing this - you can create resources in the resource editor and load them via the Properties.Resources object, you can add image files (for instance) to the project, have them compiled as resources, and load them using their URI, and there are plenty of other ways that I don't know about.
The resources available to FrameworkElements via their resource dictionaries are a different thing. Well, sort of. Here's an example:
<Window.Resources>
<Image x:Key="MyImage" Source="images/myimage.png"/>
</Window.Resources>
This creates an Image object and adds it to the Window's resource dictionary with a key of MyImage You can then reference that object via the StaticResource markup extension in XAML, or the FindResource method in code.
Setting the Source attribute on the Image element in XAML also makes the XamlReader use the ResourceManager to read the image data from the project's compiled resources at runtime when it creates the Image object.
In practice, this is nowhere near as confusing as it is when you're first learning WPF. I never get resources that ResourceManager loads and resources stored in resource dictionaries mixed up.
And when exactly is that object created?
Any object defined by a XAML element is created when the XamlReader reads the element. So this:
<Window.Resources>
<local:Person x:Key="MyPerson"/>
</Window.Resources>
instantiates a new Person object and adds it to the Window's resource dictionary with a key of MyPerson. It's exactly equivalent to doing this in the Window's code-behind:
AddResource("MyPerson", new Person());
So why don't you just do it in code-behind? Two reasons:
First, it's consistent. If you define all your resources in XAML, you only need to look in XAML files to find what your resources are. If you define them in both XAML and code-behind, you have to look in two places.
Second, the IDE knows about resources that you define in XAML. If you type
<TextBox Text="{Binding {StaticResource MyPerson}, Path=Name}"/>
in your XAML, the IDE will let you know if you haven't defined, somewhere in the hierarchy of resource dictionaries, a resource whose key is MyPerson. But it doesn't know about resources that you've added in code, and so even though the resource may actually be findable at runtime, the IDE will report it as a problem.
Think about it this way: all FrameworkElements (Windows, Buttons, other Controls, etc), as well as the Application object, contain a Dictionary of Resources. Whenever you define a resource in XAML as shown here:
<Window>
<Window.Resources>
<SolidColorBrush x:Key="myBrush" Color="Red"/>
<DataTemplate x:Key"myTemplate">
<!--Template definition here -->
</DataTemplate>
</Window.Resources>
</Window>
It's like doing something like this in code:
class Window
{
void Window()
{
this.Resources.Add("myBrush", new SolidColorBrush(Brushes.Red));
this.Resources.Add("myTemplate", new DataTemplate());
}
}
You can put all kinds of objects as Resources. Anything that you would like to re-use throughout your application, you can define it as a Resource.
Now, when you do use a "{StaticResource}" as follows:
<Button Background="{StaticResource myBrush}"/>
This is like telling WPF to search for the corresponding "myBrush" resource and apply it to the Background property. What will happen is WPF will first search the resource in the Button's resource dictionary, and if it's not found will search its parent, then its parent's parent, and so on up to the application's resources.
The "static" thing in "StaticResource" just distinguishes it from the other type of resource-lookup called "DynamicResource". The difference between the two is answered in this link.
When applied to Binding, it also works the same way. Say, for instance, you have the following resource in your XAML:
<local:Person x:Key="MyPerson" Name="Title"/>
and used it as:
<TextBlock Text="{Binding Source={StaticResource MyPerson}, Path=Name}"/>
In this case, what will happen is something like this:
Binding b = new Binding();
b.Source = FindResource("MyPerson");
b.Path = "Name";
[TextBlock].SetBinding(TextBlock.TextProperty, b);
Again, the "{StaticResource}" markup in the XAML tells WPF to search for the corresponding resource and set it as the value for the a property. In this case, the property is Binding's "Source" property.
That's the basics. Hope you find this helpful

WPF: Accessing resources in a control assembly

I have a control for which i want to declare resources in a xaml file. if this was a user control i could put the resources in an <UserControl.Resources> block and reference them in the code via this.Resources["myResourceKey"] how do i achieve the same functionality in a control. at the moment the only link to xaml i have is through the controls static constructor, to reference the style (and control template)
static SlimlineSimpleFieldTextBlock() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(SlimlineSimpleFieldTextBlock), new FrameworkPropertyMetadata(typeof(SlimlineSimpleFieldTextBlock)));
}
but even if i add a block to the xaml <Style.Resources> I dont seem able to reference them (as the Style is null at the OnApplyTemplate stage) and even if i did it would mean if someone eles overrode the style i would lose my resources.
Construct your resource key using ComponentResourceKey. Normal resource keys are searched for only up the visual tree and in your application resources. But any resource key that is a ComponentResourceKey is also searched for in the theme dictionary for the assembly containing the type. (This is also true for Type objects used as resource keys.)
In your Themes/Generic.xaml of the assembly containing a control called "Sandwich" you might have:
<SolidColorBrush x:Key="{ComponentResourceKey local:Sandwich, Lettuce}"
Color="#00FF00" />
<ControlTemplate x:Key="{ComponentResourceKey local:Sandwich, PeanutButter}" ...>
...
</ControlTemplate>
You can reference these resources in code like this:
var lettuce = (Brush)FindResource(
new ComponentResourceKey(typeof(Sandwich), "Lettuce"));
var penutButter = (ControlTemplate)FindResource(
new ComponentResourceKey(typeof(Sandwich), "PeanutButter"));
You can also refer to these resources in XAML like this:
<Border Background="{StaticResource ResourceKey={ComponentResourceKey local:Sandwich, Lettuce}}" />
Both of these forms of reference work from anywhere that FindResource can be used, which is inside the code or XAML for any object derived from FrameworkElement, FrameworkContentElement or Application.
Additional notes
The search algorithm for a ComponentResourceKey resource involves only the assembly contaning the specified type, not the type itself. Thus a control of type Soup could use a ComponentResourceKey of {ComponentResourceKey local:Sandwich,Seasonings} if the Soup and Sandwich classes were in the same assembly. As long as everything about the ComponentResourceKey matches exactly and the resource is actually in the same assembly as the given type, the resource will be found.
Also note that although it is possible to use pack URI to load a ResourceDictionary from another assembly, it is a bad idea to do so. Unlike the Themes/Generic.xaml solution you actually have to modify the application using your controls, and it also suffers from multiple-inclusion and overridability problems.
Whenever you are using Themes/Generic.xaml you must have your ThemeInfoAttribute set correctly on that assembly. You can start with this in your control library's AssemblyInfo.cs:
[assembly:ThemeInfoAttribute(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

Programmatically Accessing a Silverlight Static Resource

I'd like to programmatically access static resources much as I would in XAML:
<TextBlock Text="{Binding Source={StaticResource My.Text.Key}}" />
This works whether my static resource is defined on the TextBlock, some parent element (e.g. UserControl) or even the application. It seems that either the StaticResource binding expression knows how to walk up the element tree, or the element itself does. I'd like to do the same thing programmatically:
<UserControl x:Class="MyCustomControl" ...>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources.xaml"/> <!-- Sets 'My.Text.Key' to System.String 'Hello, World!' -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
</UserControl>
public partial class MyCustomControl
{
public MyCustomControl()
{
InitializeComponent();
string myCustomValue = this.Resources[MyCustomValue] as string; // myCustomValue becomes null!
}
}
Even in this simple test, my resource can't seem to be accessed programmatically. And this is the simplified version of what I was trying to really do: find a static resource via an element that I have a custom dynamic property attached to (e.g. uiElement.Resources[key]).
Despite your comment to the contrary I doubt the use of "." in your resource key is really the source of your problem. In this situation the "." has no special meaning and would not impact how the resource is accessed. (I've tried and failed to reproduce any problem with it).
There is though a very big difference between using the {StaticResource MyName} mark up extension and an attempt to find the resource programmatically.
The markup extension causes the XamlParser to look for the specified key the Resources property of the FrameworkElement to which the property being assigned belongs. If the key is not found it looks for it in the parent FrameworkElement and it keeps going until it reaches the root FrameworkElement. If it is still not found it has a look in the Application's Resources property.
On the other hand this code:-
string myCustomValue = this.Resources[MyCustomValue] as string;
sf just looking in the single Resources property for the user control. No attempt is made to hunt down the key in ancestors or in the application resources. Its a simple Dictionary lookup. This I suspect is what was really tripping you up.
Having said that I would say the using "." in a resource key may not be a good idea. The "." does have meaning in various XAML scenarios already so using it in key names as well has the potential to confuse a developer reading the code even though Silverlight is quite happy with it.

How to set default WPF Window Style in app.xaml?

I am trying to set the default Style for every window in my WPF Windows application in my app.xaml. So far i have this in app.xaml:
<Application.Resources>
<ResourceDictionary>
<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
<Setter Property="Background" Value="Blue" />
</Style>
</ResourceDictionary>
</Application.Resources>
I can get the window to appear with this style when running the app (but not in VS designer) by specifically telling the window to use this style via:
Style="{DynamicResource WindowStyle}
This works, but is not ideal. So how do I:
Have all windows automatically use the style (so i don't have to specify it on every window)?
Have VS designer show the style?
Thanks!
To add on to what Ray says:
For the Styles, you either need to supply a Key/ID or specify a TargetType.
If a FrameworkElement does not have an
explicitly specified Style, it will
always look for a Style resource,
using its own type as the key
- Programming WPF (Sells, Griffith)
If you supply a TargetType, all instances of that type will have the style applied. However derived types will not... it seems. <Style TargetType="{x:Type Window}"> will not work for all your custom derivations/windows. <Style TargetType="{x:Type local:MyWindow}"> will apply to only MyWindow. So the options are
Use a Keyed Style that you specify as the Style property of every window you want to apply the style. The designer will show the styled window.
.
<Application.Resources>
<Style x:Key="MyWindowStyle">
<Setter Property="Control.Background" Value="PaleGreen"/>
<Setter Property="Window.Title" Value="Styled Window"/>
</Style>
</Application.Resources> ...
<Window x:Class="MyNS.MyWindow" Style="{StaticResource MyWindowStyleKey}"> ...
Or you could derive from a custom BaseWindow class (which has its own quirks), where you set the Style property during the Ctor/Initialization/Load stage once. All Derivations would then automatically have the style applied. But the designer won't take notice of your style You need to run your app to see the style being applied.. I'm guessing the designer just runs InitializeComponent (which is auto/designer generated code) so XAML is applied but not custom code-behind.
So I'd say explicitly specified styles are the least work. You can anyways change aspects of the Style centrally.
Know this is years later, but since the question is still up here...
Create a resource dictionary in your project (Right-click the project...)
I'll create a new folder under the Project called "Assets" and
put "resourceDict.XAML in it.
Add the code to resourceDict.XAML:
<Style x:Key="WindowStyle" Target Type="Window" >
<Setter Property="Background" Value="Blue" />
</Style>
In your Project XAML file add the following under Window:
<Window.Resources>
<ResourceDictionary>
<!-- Believe it or not the next line fixes a bug MS acknowledges -->
<Style TargetType="{x:Type Rectangle}" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Assets/resourceDict.XAML" />
</ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
</Window.Resources>
ref the following web site: Trouble referencing a Resource Dictionary that contains a Merged Dictionary
"There is a bug: if all your default styles are nested in merged dictionaries three levels deep (or deeper) the top dictionary does not get flagged so the search skips it. The work around is to put a default Style to something, anything, in the root Dictionary."
And it seems to fix things reliably. Go figure...
And finally, under Window, maybe after Title, but before the final Window '>' :
Style="{DynamicResource windowStyle}"
And you'll need to add the code in steps 3 & 4 to every project to which you want the style to apply.
If you wanted to use a gradient background rather than a solid color, add the following code to the resourceDict.XAML:
<LinearGradientBrush x:Key="windowGradientBackground" StartPoint="0,0"
EndPoint="0,1" >
<GradientStop Color= "AliceBlue" Offset="0" />
<GradientStop Color= "Blue" Offset=".75" />
</LinearGradientBrush>
And modify your Style Setter for the background color to read:
<Setter Property="Background" Value="{DynamicResource
windowGradientBackground}" />
Steps 3 & 4 need to be repeated in each project.XAML file as described above, but hey, you get uniform Windows across the Solution! And the same process could apply to any controls you want to have a uniform look as well, buttons, whatever.
For anyone coming into this late, hope this helps as I'm sure the original posters got this all figured out years ago.
Paul
The designer is not working because you're specifying a DynamicResource. Please change this to StaticResource and all will be well.
To apply to all windows, you should remove the x:Key from the style. Setting the TargetType implicitly sets the x:Key to whatever is in TargetType. However, in my tests, this is not working, so I am looking into it.
If I set the TargetType to x:Type TextBlock, the designer works perfectly, it just seems to be the Window that is showing different behaviour.
You can add this code to your App.xaml.cs file:
FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata
{
DefaultValue = Application.Current.FindResource(typeof(Window))
});
After this, the style applied to the Window type will also apply to all types derived from Window
I investigated this one for some days now and made it work through the Constructor of my custom Window Class:
public class KWindow : Window
{
public KWindow()
{
this.SetResourceReference(StyleProperty, typeof(KWindow));
}
static KWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(KWindow), new FrameworkPropertyMetadata(typeof(KWindow)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// gets called finally
}
}
Hope it helps someone
For those this struggling with a solution to the problem: How can I have a custom style be automtically applied to all my Window derived types? Below is the solution I came up with
NOTE: I really didn't want to derive from the Window type or have to insert XAML on each window to force a style update etc. for reasons specific to my project (consumers of my product us my generic reusable style library and create their own layout/windows etc.) so I was really motivated to figure a solution out that worked that I was willing to live with any side effects
Need to iterate through all the instantiated windows and simply force them to use the new custom style you have defined for the Window type. This works great for windows that are already up but when a window or child window is instantiated it won't know to use the new/custom type that has been declared for its base type; the vanilla Window type. So the best I could come up with was to use the LostKeyBoardFocus on the MainWindow for when it loses Focus to a ChildWindow (IOW When a child window has been created) and then invoke this FixupWindowDerivedTypes().
If someone has a better solution for "detecting" when any kind of window derived type is instantiated and thus call the FixupWindowDerivedTypes() that would be great. There may be something useful with handling the WM_WINDOWPOSCHANGING in this area as well.
So this solution is not elegant per say but gets the job done without me having to touch any code or XAML related to my windows.
public static void FixupWindowDerivedTypes()
{
foreach (Window window in Application.Current.Windows)
{
//May look strange but kindly inform each of your window derived types to actually use the default style for the window type
window.SetResourceReference(FrameworkElement.StyleProperty, DefaultStyleKeyRetriever.GetDefaultStyleKey(window));
}
}
}
}
//Great little post here from Jafa to retrieve a protected property like DefaultStyleKey without using reflection.
http://themechanicalbride.blogspot.com/2008/11/protected-dependency-properties-are-not.html
//Helper class to retrieve a protected property so we can set it
internal class DefaultStyleKeyRetriever : Control
{
/// <summary>
/// This method retrieves the default style key of a control.
/// </summary>
/// <param name="control">The control to retrieve the default style key
/// from.</param>
/// <returns>The default style key of the control.</returns>
public static object GetDefaultStyleKey(Control control)
{
return control.GetValue(Control.DefaultStyleKeyProperty);
}
}
Considering Gishu's answer I figured out one more workaround. But it could be little bit weird.
If you use MVVM pattern you could remove code-behind of your window and x:Class markup in XAML file. So you will get an instance of window or your custom window but not a some instance of 'MainWindow' class that is derived from 'Window' class and marked as partial.
I'm making VS-like window so I had to inherit window class and extend it functionality. In that case it will be possible to make new window class as partial that would allow us to make code-behind without inheritance.
you will save all the styles in one xaml file(example design.xaml)
and then call that (design.xaml) xaml file in all the pages like this way
Like:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Design.xaml"/>
</ResourceDictionary.MergedDictionaries>

Resources