I want to define some resources in my App.Xaml for fontsize.
This type of thing will work:
<sys:Double x:Key="FontLarge">24</sys:Double>
But I want to get the value from a :xStatic so something like this:
<sys:Double x:Key="FontLarge">{x:Static local:Settings.FontLarge</sys:Double>
or
<sys:Double x:Key="FontLarge" Value="{x:Static local:Settings.FontLarge"></sys:Double>
Neither of these work though. Is this possible and what would be the syntax?
I don't think that there is a way to bind Double value using x:Static (I may be wrong though).
But there is always a way using code behind which you can use. If this is meant to be in App.Xaml, you can write
App.Current.Resources.Add("FontLarge", Settings.FontLarge);
If some other class, you can just drop the App.Current and that would work.
Related
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.
Please consider the following XAML markup (App.xaml file in Visual Studio 2010):
<Application x:Class="UpdateTrigger.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UpdateTrigger"
xmlns:clr="clr-namespace:System;assembly=mscorlib"
StartupUri="MainWindow.xaml">
<Application.Resources>
<clr:String x:Key="MyString">My string</clr:String>
</Application.Resources>
</Application>
Can I write into MyString much like a variable in a C# program? That is what I am trying to do: I am trying to declare and define a variable through pure XAML, without any code-behind. Is this possible?
CLARIFICATION EDIT:
If I bind MyString, for example, to a TextBox in XAML, can a user type into that TextBox? I tried, but have not been able to do this.
Is it possible to bind to and modify a resource object? Yes and no. You can do it but the object needs to be mutable, so can't be a value type like an Int32 or Boolean, or String which is an immutable reference type. The object also needs to have some property that is being modified (the Path of the Binding) - you can't replace the entire object itself.
The more important question is probably, should you do this. The answer to that is usually no but there can be cases where it can sometimes be useful, for example, declaring a ViewModel instance directly in the View XAML to provide easy designer support. In general it's almost always better to be binding to objects that are part of your code so they can easily interact with other parts of your program without relying on runtime resource lookups. If you have data that's staying in the view, like a TextBlock that just mirrors the value of a TextBox, it's usually better just to bind them directly together with an ElementName Binding rather than adding an extra middleman.
I have a default template defined for one of my classes. It works correctly and is applied as I'd expect, but I am using an attached property (detailed here, actually) for which I have to specify a DataTemplate. I have been unable to find an acceptable way of specifying my default template in XAML.
My data template looks something like this:
<DataTemplate DataType="{x:Type myNS:MyType}">
....
</DataTemplate>
So far I have attempted to specify it like this
attached:property.MyDataTemplate="{StaticResource {x:Type myNS:MyType}}"
but this throws an exception at runtime ("Cannot find resource named 'My.Full.NameSpace.MyType'. Resource names are case sensitive.").
I've done enough looking around to know that other people have similar problems but I haven't been able to find a decent solution. I am considering simply maintaining a duplicate DataTemplate with an x:Key so I can point at it. Is there a better way?
UPDATE:
Alright - it's been pointed out that this does work if you use DynamicResource instead of StaticResource. This does not make sense to me.
I've read a fair bit on DynamicResource vs StaticResource (among other thing, I read this thread). Here's what I do know:
If I specified a x:Key instead of a DataType I can use this template as a StaticResource.
When the page loads the template is in the dictionary and can be retrieved in code
var myTemplate = this.Resources[new DataTemplateKey(typeof(MyType))];
Can anyone explain what's happening here?
Give this a try: (Switch StaticResource to DynamicResource)
attached:property.MyDataTemplate="{DynamicResource {x:Type myNS:MyType}}"
My guess for the reason why this works:
This answer gives a good difference between StaticResource and DynamicResource. I'm guessing this Default template data isn't available when StaticResource tries to retrieve it(during the loading of the XAML) which isn't the case for DynamicResource
I guess, the problem because of your DataTemplate has DataTemplateKey with type myNS:MyType, but property.MyDataTemplate="{StaticResource {x:Type myNS:MyType}}" tries to find resource with string key matching your type full name.
Instead of using "{StaticResource {x:Type myNS:MyType}}" you should use:
"{StaticResource {DataTemplateKey {x:Type myNS:MyType}}}"
or its full equivalent:
"{StaticResource ResourceKey={DataTemplateKey DataType={x:Type myNS:MyType}}}".
Also, you don't need DynamicResource in this case.
if all Styles and Converters are stored in shared resource dictionary file (styles.xaml), and this file is used from various windows.
Is it possible, to pass a parameter to that file, and propagate that parameter to the converters?
I am looking for a way to pass a "origin" type parameter, so that the converters could be aware which place they are being used from? Just a hint of which window/grid is using the converter at the moment..
See this article for Converters with parameters. I assume you define the Converter resource in Resource dictionary.
http://www.switchonthecode.com/tutorials/wpf-tutorial-binding-converters
I wonder if something like this will work:
Add a reference to the System namespace in the declaration of each Window or UserControl where you want this.
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Then in your resources section set things up like this:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<sys:String x:Key="WinConvertParam">IDTextForThisWindow</sys:String>
</ResourceDictionary>
</Window.Resources>
Your binding syntax could then look something like this:
{Binding SomeProperty,
Converter={StaticResource thatConverterIWrote},
ConverterParameter={StaticResource WinConvertParam}}
...and your Convert or ConvertBack methods in your conversion classes then become aware of the Window that's using them, provided you vary the value of that <sys:String/> from file to file.
What do you think?
While defining style in resource dictionary you can use either
x:Name="xyz"
and
x:Type="xyz".
and can reference this style in XAML like {StaticResource xyz}.
Most examples use 'x:Key', and the difference between 'name' and 'key' is that using 'x:name' lets you use this style definition code-behind?
FIXES:
The question is totally wrong. What was intended to be asked was the difference between x:Key and x:Name. But didn't go trying this code myself, but was just relying on memories - thought I have both in ResourceDictionary, which was wrong. And I also didn't have such code in
<xxx.Resources >
sections, since it doesn't work either. You can't reference Style that doesn't have x:Key (x:Name doesn't work here), and adding two styles without x:Key throws exception since both get the same (empty?) key in dictionary.
Ray puts all the difference in a very nice way, thanks.
My fault
This is a trick question. In fact, you cannot define a style in a ResourceDictionary using either
x:Type="xyz"
or
x:Name="xyz"
Here is the difference:
x:Type="xyz" is not valid XAML syntax.
x:Name="xyz" is actually valid XAML syntax that names an object (which affects the generation of code-behind) but does not provide a dictionary key.
x:Key="xyz" is also valid XAML syntax that provides a dictionary key but does not name an object.
In a dictionary a key is required, so you must specify x:Key (except that for FrameworkTemplate and its subclasses the key can be inferred from the TargetType or DataType). In a dictionary you may also specify x:Name if desired but it does not affect the key.
Note that x:Type is a markup extension that is predefined by XAML, whereas x:Name and x:Key are actual XAML keywords. So x:Type can only be used in markup extension syntax as the value of a property:
something="{x:Type whatever}"
whereas x:Name and x:Key are attributes that can be used on elements.
x:Name allows you to create a reference that you can use by name.
x:type allows you to create a reference that is used by that type
for instance
<Style TargetType="{x:Type Button}">
...
</Style>
creates a style that will automatically affect buttons