Manually parse string as XAML Attribute - wpf

How does the XAML Parser convert the string "Red" in Foreground="Red" to a SolidColorBrush? Allthough I know the Types have System.ComponentModel.TypeConverter defined, I doupt that the WPF XAML parser acutally always uses those to convert the string to the brush. Are there any XAML APIs apart from XamlReader.Load (wich wants a valid xml string) that I could use to parse a single string as if it where an attibute for a certain property?

The XAML parser (for WPF) really does actually use the type converter of the property or property type specified. There are a few hard-coded short-cuts but they are for performance and do not change the semantics. A parser, just using attribute information, can duplicate the parser semantics (which is, for example, what Blend and Cider do).
There is no API that will convert a value exactly as XAML would mainly because many type converts only work in the context of a XAML parse. For example, type converters can refer to namespaces defined in the XAML file (which changes depending on where the value is in the XML file) as well as other ambient information base URI base for the file. These are only really applicable when the XAML file is being parsed.
The closest you can come to is asking for the property descriptor for the property from the type descriptor and using the Converter property. This will scan the appropriate attributes to create the correct type converter.

I believe you can take advantage of this yourself. XamlReader knows the target type (the type of the property to which the string must be applied). You would register a TypeConverter for that property's type.
EDIT this will work for you when it comes to SolidColorBrush:
var colorString = ...;
var converter = new System.Windows.Media.BrushConverter();
var brush = (SolidColorBrush)converter.ConvertFromString(colorString);
Looking at SolidColorBrush in .NET Reflector, it seems the magic that does deserialization within XamlReader uses internal APIs around known types. I'm not sure whether you can register your own types to handle this.

Related

difference between directly mentioning property name and mentioning property using PATH keyword in WPF [duplicate]

I've seen both styles used in the same project, and I wonder if there's any semantic difference between them, or if any would be recommended over the other and why.
There is a significant difference here which you will run into as soon as you have a complex property path with typed parameters.
Conceptually they are equivalent as they both end up setting the Binding.Path, one via the parameterized Binding constructor, the other directly via the property. What happens internally is very different though as the Binding.Path is not just a string which in both cases would be passed on to the property, it is a PropertyPath.
When XAML is parsed, type converters are used to turn strings into the types expected by properties. So when you use Path= a PropertyPathConverter will be instantiated to parse the string and return a PropertyPath. Now here is the difference:
Binding(string path) invokes public PropertyPath(string, Object[])
PropertyPathConverter invokes internal PropertyPath(string, ITypeDescriptorContext)
(In the case of the Binding constructor the Object[] will be empty)
How does this matter?
If you for example have multiple indexers in a class e.g. one that expects a string and one that expects an int and you try to cast the value to target the latter, the cast will not work:
{Binding [(sys:Int32)0]}
The PropertyPath is lacking the ITypeDescriptorContext because the public constructor is invoked so the type System.Int32 cannot be resolved from the string sys:Int32.
If you use Path= however the type converter will be used instead and the type will be resolved using the context, so this will work:
{Binding Path=[(sys:Int32)0]}
(Aren't implementation details fun?)
They mean the same thing. Where they differ is in how the Binding object is instantiated and populated.
{Binding Path=Foo}
creates a Binding instance using its parameterless constructor, and then sets the instance's Path property.
{Binding Foo}
creates a Binding instance using its single-parameter constructor, and passes the value "Foo" to that constructor parameter. The single-parameter constructor just sets the Path property, which is why the two syntaxes are equivalent.
It's very much like the syntax for custom attributes, where you can also pass constructor parameters and/or set property values.
There is none.
When not specified, the Path property is assigned the value. In other words, Path is the default property of a binding.
It's like the "Content" property, which is the default property for many controls. For example
<Button>Hello</Button> Is the same as <Button><Button.Content><TextBlock Text="Hello"/></Button>
Hope that helps.
There is no semantic difference, the first property in the binding will be interpreted as the "Path" property if no property name is supplied.
It's a matter of coding style.
Update
Removed the sentence "It is the default property".
I realize that there is no formal support for "default properties", but the scenario is often referred to as the "default property", and is supported by convention.
Example, from the MSDN documentation for the Path property of the Binding markup extension:
The Binding markup extension uses Binding.Path as a conceptual "default property", where Path= does not need to appear in the expression.
I do not think I am wrong and completely misguided to use this terminology as is being suggested. I also understand how it is implemented.
Don't think there's any difference, expect perhaps the second is more explicit.

WPF Units and Code-Behind

Recently I discovered WPF supports different measurement units in XAML. Besides default DIPs, there is also support for pixels, inches and centimeters (as far as I know). This allows designer to write XAML such as this:
<Canvas>
<Line X1="0cm" X2="3cm" Y1="1cm" Y2="3cm" Stroke="Black"/>
</Canvas>
However, you cannot bind these values. Imagine we have a ViewModel with Dimension property which is a String, for example "7cm". Following won't work:
<Button Width="{Binding Dimension}">Test</Button>
FormatException gets thrown. Similarly, when creating a FrameworkElement in code-behind, like this:
Canvas1.Children.Add(new Button() { Width = "3cm", Content = "Test"});
Compilation fails because exception is thrown in constructor/wherever you try to create the control.
I wonder:
Is it possible to use natural units (in my case metric - centimeters) in code-behind?
How?
Is there a complete list of units WPF/XAML supports?
EDIT:
Here is a link from comment below, which resolves this question:
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.width.aspx
You can do this in code behind by applying the same conversion the XAML-parser uses, you do not need to reimplement this logic if you don't mind passing around strings:
button.Width = (double)new LengthConverter().ConvertFrom("2cm");
The XAML-parser uses TypeConverters to convert strings to the needed values, in the documentation page of the Width property you can see that it has a TypeConverterAttribute specifying that a LengthConverter should be used. This attribute can be used to locally override how a property should be handled, but it can also be applied at class level, so if an Employee class has this attribute specifying that an EmployeeConverter should be used said converter will be the default for properties of type Employee.
I am a bit surprised the binding does not apply this type converter, but using it inside an IValueConverter would be simple enough, in fact you could create a markup extension which constructs an IValueConverter from a type converter to make it nicely generic.
For 1) and 2) Because DIPs are device independent, you can calculate any "natural unit" to and from without problems. The exception are (unnatural :) device dependent pixels.
Create a ValueConverter that converts string values to doubles where your desired units may be specified in the string. Then you can use the ValueConverter in your Binding and calculate in your ViewModel in "natural units".
For 3) and the implementation: I have quickly googled and found nothing, but maybe will a deeper search show something. Otherwise, creating your own converter should not be very difficult. Here some conversion infos:
96DIP == 1inch == 2.54cm;
1cm == 37.8DIP;
1zoll == 1inch == 2.54cm;

How to generate predefined values for xaml property with typeconverter

If I have a control and I start typing a foreground property for it, it offers me a list of Colors, seemingly from the Colors class.
edit: I think it's actually the KnownColor enum, which is internal.
How is this achieved?
I have an attached property which is of type MyClass. I have a static class with some pre-cooked instances of MyClass. I want to achieve the same behavior described above.
I know I can use a type converter and convert from the string to an instance, but this seems a little more advanced
You will need to use a Type converter. The Xaml parser has built-in special handling of known types such as Brush and Color.

Silverlight3: Returned localized string, when binding without converter, is always in "en-US" culture

The problem:
The returned localized string for the non-string binding properties (DateTime, double...) is always set to "en-US" culture, regardless of the CurrentThread.CurrentCulture.
The solution I am looking for:
I am looking for a solution other than using a converter (The localization works properly if a converter is used), since I need to implement it in an existing large Silverlight3 application where converters were not used in the first palce.
The Question:
How to make localization work with non-string binding properties, without converters ?
thnx
Krsto
Do the following in the constructor of your App.Xaml:
Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-SE");
And then this in the constructor of every user control:
this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);
That might work, give it a try. Of course you will have to adjust the culture to whatever it is you want to do.

Are value converters instantiated per-binding in WPF?

Is a separate WPF value converter object instantiated for each binding that a particular value converter class is used in?
I am trying to create a two-way bit-to-boolean value converter. I would like to be able to bind a bool property (such as IsChecked) to a bit in a value type (like a ushort). I'm using the converter's parameter arguments to specify the bit. Implementing the ConvertBack() method is easy, but Convert() is little trickier.
In Convert() I need to know what the value of the entire ushort is so I can toggle just the single bit I am interested in. I was thinking of just using a member variable in my value converter class to temporarily store this whenever ConvertBack() is called, thus leading to the above question: does each binding get its own value converter instance?
If you use a converter defined in your resources, it will be shared amongst your properties.
If you need unique converters:
If you create a specific converter for a property, however, it will not be shared. Either option is workable. You can even use multiple converters (of the same type, with different keys) in your resources, which will create unique instances.
Create a constructor and destructor in your converter and set breakpoints within to tell for sure. I just created a simple example and it looks like only one converter was created for my multiple viewmodels that were using the constructor

Resources