How does a XAML definition get turned into an object instance? - wpf

XAML allows you to specify an attribute value using a string that contains curly braces. Here is an example that creates a Binding instance and assigns it to the Text property of the TextBox element.
<TextBox Text="{Binding ElementName=Foo, Path=Bar}"/>
I want to extend XAML so that the developer could enter this as valid...
<TextBox Text="{MyCustomObject Field1=Foo, Field2=Bar}"/>
This would create an instance of my class and set the Field1/Field2 properties as appropriate. Is this possible? If so how do you do it?
If this is possible I have a followup question. Can I take a string "{Binding ElementName=Foo, Path=Bar}" and ask the framework to process it and return the Binding instance it specified? This must be done somewhere already to make the above XAML work and so there must be a way to ask for the same thing to be processed.

The Binding class is a Markup Extension. You can write your own by deriving from System.Windows.Markup.MarkupExtension.
ElementName and Path are simply properties on the Binding object.
As for the followup you can create a new Binding in code by instantiating the Binding object. I do not know of a way to process a string through.

take a look at markupextensions
http://blogs.msdn.com/wpfsdk/archive/2007/03/22/blogpost-text-creatingasimplecustommarkupextension.aspx

Related

WPF: Does static Resource with Binding as "TwoWay' supports two way binding?

<TextBox Name="CustomerName" Height="30" Margin="5"
Text="{Binding Source={StaticResource MyCustomerData},
Path=CustomerName, Mode=TwoWay}" Grid.Row="0" Grid.Column="1" />
Above is my xaml snippet
MuCustomerData is my class which implements INotifyPropertyChanged interface and it has a property CustomerName which shall notify about the changes using PropertyChanged event to the View (UI)
Here I bind my class(MyCustomerData) as StaticResource and binding mode as TwoWay. Will this actually work two way? or I should use my class as Dynamic Resource to make the binding work two way?
Since only once a StaticResource would get loaded and any further changes will not be taken when it is staticresource ....
your thoughts?? I just read this http://www.codeproject.com/Articles/393086/WPF-StaticResource-vs-DynamicResource ..Pls do take a look on this article ..
StaticResource and DynamicResource refer to WPF's Resources, not Bindings.
StaticResource evaluates once (usually when the XAML is parsed), and is never evaluated again because WPF assumes the resource is static and won't ever change.
DynamicResource means the resource is dynamic, so evaluate it whenever the value is needed.
In your case, the Source property of your binding will be evaluated once, and never again since it is set to a StaticResource. If you change the MyCustomerData object to a new object, the binding won't evaluate itself again to reflect the change.
But the actual property, CustomerName, will get updated as needed because it is bound using a TwoWay binding.
To look at it another way, you're creating a binding that says something like
var b = new Binding();
b.Source = MyCustomerData;
b.Path = "Name";
b.Mode = TwoWay;
When you set b.Source using a StaticResource, then think of the binding evaluating using b.Source.Name. But if you were to use a DynamicResource, think of it as evaluating with MyCustomerData.Name, and so it would use the current version of MyCustomerData.
So you could set MyCustomerData = new MyCustomerData();` after the binding has been evaluated once, and a dynamic resource would evaluate that correctly, while a static resource would not.
StaticResource or DynamicResource have nothing to do with Binding.
I will try to explain this as simple as possible for you.
StaticResource means that you know in which resource dictionary the object with specific key is being hold. Thats it. Nothing else. You know its either in StackPanel.Resources or maybe Window.Resources.
DynamicResource is gonna be used when you add/load somewhere in your VisualTree an object with a key into resources dictionary. It's position is unknown at app's startup and so it needs to be loaded dynamically.
Remember no matter what kind of language you use for programming whenever you see dynamics being mentioned it means something is happening at runtime and not right from beginning.
Best example would be dynamically generated objects in C#. Those objects allow you to define a property at runtime. When the app is started the object is pretty empty.
Now back to Binding. In your case you tell the Binding where the Source is and from that point on Binding will work without giving a s**t how is Source defined.

How to bind a textblock's text through XAML using a property?

I am working on a Silverlight application, and I want to bind the simple text property of textblock through a property of string type.
What I did was:
<TextBlock Text="{Binding Name}"/>
Code behind:
public string Name{get;set;}
Name = "Testing..!";
but it will not work.
To expand on anatoliiG's answer (which will work): Data binding refers to properties on the DataContext property of the current element by default. This means that your
<TextBlock Text="{Binding Name}" />
is actually translated to
Set the value of the Text property to this.DataContext.Name
(DataContext is inherited, so if it is not explicitly set on the TextBlock it will check the parent, then the parent of the parent etc etc)
You can resolve your problem in one of two ways:
You can set the value of this.DataContext on the parent to the parent itself (as anatoliiG suggests). This means that when it looks up this.DataContext.Name it will be checking the Page itself, which is where your Name property is found.
You can change your Binding so it looks at the Page instead of Page.DataContext when it is looking up bindings. You can achieve this using the RelativeSource markup extension:
This translates to:
Find the first ancestor of the TextBlock that is of type Page, and bind to the Name property on that object
As a final note, you will also need to implement INotifyPropertyChanged on your DataContext object if you are going to ever change the value of Name.
Oh, and you should be using view models as the DataContext instead of the Page itself!
Answer to your question is: in Page_Loaded event set LayoutRoot.DataContext = this;. But it is more hack, than good practice.
You should take a look into MVVM pattern and INotifyPropertyChanged and create ViewModel which will contain this property.

Why is StaticResource required?

First, I searched long and hard to try to find the answer to this. I resorted to here for expert help with this problem.
I am currently reading a book about programming for the Windows Phone 7. I am currently learning about Data Binding (and doing pretty good too). I have come across a question about the formatting of DataBinding in WPF, mostly about the function of StaticResource.
In the following code you are about to see, there is a slider and a text block. The text block is binded to the slider so that when the slider is moved, the text block's value changes. A class has been created, TruncationConverter, and has can be called in XAML with the keyword "truncate". It is declared in phone:ApplicationPage.Resources.
So, this is right
<TextBlock Name="txtblk"
Text="{Binding ElementName=slider,
Path=Value,
Converter={StaticResource truncate}}"
And this is wrong
<TextBlock Name="txtblk"
Text="{Binding ElementName=slider,
Path=Value,
Converter=truncate}"
The book never really went in to explaining why one must put StaticResource before the function.
So, the question is, why do you need to put StaticResource before the call? What does it do, what is its function? Why is there an error when you don't put StaticResource before truncate.
Thanks in advance!
The constructor for the Converter class uses a markup extension in order to work. The markup extension requires that the object be previously defined in the object graph, and this is was done when you assigned your converter class a key. When the Xaml parser sees StaticResource (or DynamicResource) it starts looking upward in the object graph until the value is found. At runtime, an instance of the class is created and used to do your conversions. Once an instance of your converter has been created, WPF uses it for the life time of your application, hence 'Static'.
The 'StaticResource' may seem extraneous or redundant because a converter cannot be a DynamicResource, but such are the syntax rules of Xaml.
Basically placing StaticResource is telling it to find the external property likely in a ResourceDictionary which holds the function of for example "truncate"
So like another example would be if I go and say create another control or converter or even a brush or other instance I wish to be made available throughout other elements of an application, it's created as an available resource that is only editable in one spot (a resource dictionary) but usable by all, eg; a StaticResource
Like when you placed your slider and your Textblock, it by default is calling a style for each found in your CoreStyles resource dictionary. If I wanted to change what they did or how they look for example I could copy the resource, edit it as necessary, rename it, and say call it by

Current binding value

I'm writing markup extension. I have XAML like this
<TextBlock Text="{ui:Test SomeInfo}" />
and TestExtension with constructor taking one string argument. I'm getting "SomeInfo" string so everything is find. Now I want to nest extensions and write something like
<TextBlock Text="{ui:Test {Binding PropName}}" />
and it does not work as is. I had to add constructor which takes one argument of System.Windows.Data.Binding type.
Now I need to know
How should I retrieve a current value from the Binding object?
When should I do this? Should I subscribe to changes some way or ask for that value every time in ProvideValue method?
Update1 PropName should be resolved against DataContext of TextBlock.
Update2 Just found related question: How do I resolve the value of a databinding?
Bindings like this will not work because your MarkupExtension has no DataContext and it does not appear in the visual tree and i do not think you are supposed to interact with binding objects directly. Do you really need this extension? Maybe you could make do with the binding alone and a converter?
If not you could create a dedicated class which has bindable properties (by inheriting from DependencyObject), this however would still not give you a DataContext or namescope needed for ElementName or a visual tree needed for RelativeSource, so the only way to make a binding work in that situation is by using a Source (e.g. set it to a StaticResource). This is hardly ideal.
Also note that if you do not directly set a binding the ProvideValue method will only be called once, this means that even if you have a binding in your extension it may not prove very useful (with some exceptions, e.g. when returning complex content, like e.g. an ItemsControl which uses the binding, but you set the extension on TextBlock.Text which is just a string), so i really doubt that you want to use a MarkupExtension like this if the value should change dynamically based on the binding. As noted earlier: Consider converters or MultiBindings for various values instead.

Is there any difference in x:name and name for controls in xaml file?

I am new in Silverlight.
When I add some control to my xaml file with Visual Studio it set controls name with Name property, but there is also x:Name.
Is there any difference and when to use each of them?
Thanks.
In Brief
Yes there is a difference. The bottom line is that x:Name can be used on object elements that do not have Name properties of their own.
A longer explanation
You can only use Name on an element that represents an object that actually does have a Name property. For example anything that derives from FrameworkElement.
The x:Name attribute may be placed on any element that represents an object regardless of whether that object actually has a Name property. If the object does have a Name property then the value of x:Name will be assigned to it hence you can't have both x:Name and Name on the same element.
When an object has a Name property or an x:Name property the value of that property is associated with the objects entry in the object tree. It is via the object tree that the FindName method of a FrameworkElement can find an object. FindName can find objects by name even if that object does not carry a Name property of its own since it uses the name recorded in the object tree.
The autogenerated code for a UserControl will contain field definitions for any element that that has a Name or x:Name property. The InitialiseComponent method that is generated will use the FindName method to assign values to these fields.
Example
The above Xaml creates two fields LayoutRoot of type Grid and MyBrush of type SolidColorBrush. If you were to change x:Name="LayoutRoot" to Name="LayoutRoot" that would change nothing. Grid has a Name property. However try changing x:Name="MyBrush" to Name="MyBrush". That doesn't work because SolidColorBrush doesn't have a name property. With the above Xaml you can then do code like this:-
public MainPage()
{
InitializeComponent();
MyBrush.Color = Colors.LightGray;
}
Open the definition of InitializeComponent and take a look at the auto generated code.
No, you just can't use them both. x:Name is what the XAML preprocessor actually uses and Name is just a convience property provided on the FrameworkElement class to set it.
From the MSDN reference:
If Name is available as a property on an element, Name and x:Name can be used interchangeably, but an error results if both attributes are specified on the same element.
Short answer: if you're writing stuff out in XAML, it's probably best to just use x:Name consistently.
Long answer: A previous answer mentioned that Name is a "convienience" property for accessing x:Name. That's correct. However, now that the tools environment for XAML in both Visual Studio and the Expression series has really matured and you are seeing more and more tool-generated XAML, you are also probably seeing more and more x:Name as opposed to Name. The tools prefer x:Name because that way they don't take a somewhat risky dependency (potentially specific to framework) re: how x:Name and Name are really the same, and they don't need to flipflop between setting Name if something happens to be a FrameworkElement and then x:Name on something like a Storyboard and generating a duality if you were to look at this XAML through something like a DOM. In other words, the "Name" attribute in XAML really is a lot less "convenient" to use nowadays than might have been conceived of in the original API design. Part of the "convenience" was to not have to map x:, but you have to do that anyways for x:Class and by now pretty much everyone has gotten used to using x: attributes and the general principles of XAML markup effectively.
I'm not sure of the statement made by the original poster that VS encourages using Name. Yes, Name appears as an intellisense option, but so does x:Name. And all the cases I see in the templates where an object is given a starting name are using x:Name even tho most of these are FrameworkElements.

Resources