Right. So moving from WPF to UWP, I'm trying to use x:Bind to get compile-time benefits. Simple scenarios work fine; however I have found a number of issues that I was not able to solve. They are all related, so I thought I'd post them in one place:
I haven't been able to make Intellisense work with x:Bind. I have set DataContext (as well as d:DataContext just as we do in WPF) both in XAML and in the constructor, but it won't show members no matter what. Has anyone done this successfully?
Then I read somewhere that in UWP, DataContext is always set to Page's code-behind (really??) and that I need to define a ViewModel type property in the code-behind and then use that property in x:Bind. Is this correct? I tried it and it works but gives rise to the next question.
If I define a property of ViewModel type in Page's code-behind, Any sub-properties that raise PropertyChanged notifications do not update the UI. For example, if the code-behind property is named Game (of type GameVM) and there is a public property in GameVM named Player (of type GamePlayer), and in turn GamePlayer contains a property named Name, the x:Bind path will look like {x:Bind Path=Game.Player.Name}. But if I do this, any change notifications raised from within Name property do not update Page's UI.
One alternate I tried was to listen to PropertyChanged at each level and then bubble it up the hierarchy, but that hasn't worked. Even if it does, doing this seems a bit too much work. In WPF sub-properties like Game.Player.Name work properly without having to doing property change bubbling. Or am I missing something?
Right. After playing with it for a few days and searching numerous references, here are my findings:
{x:Bind} lacks design-time support. The feature is on the wishlist though. You may want to upvote it there.
(The new version of Visual Studio 15.4.4 does support Intellisense in {x:Bind}in the required way.)
{x:Bind} uses code-behind as its DataContext. So you need to define a public property of your ViewModel type in the code-behind and then use it in your {x:Bind} path.
As pointed out by IInspectable, the default mode for {x:Bind} is OneTime, unlike {Binding} which uses OneWay or TwoWay in almost all cases. So you need to explicitly specify Mode in your binding. People coming from WPF should take special care of it.
Sub-properties that implement notification change work perfectly fine in {x:Bind}. There is no need of bubbling these notifications upwards in the property hierarchy. The problem I was facing (#3 in the question) was because my sub-property was of type List<T>. I changed it to ObservableCollection<T> and it started working.
Hope this works somebody down the road.
Well as a beginner, the only question I can answer for you is the first one. Intellisense does not work inside the {x:Bind}. The members are never shown there in UWP for some unknown reasons. As for the next two questions of yours, I am still working on them.
I ran into the same challenge that you have seen. In my experience, in order to create the compile-time binding and have it update with custom objects as properties, the Page class seems to need to know about the data context and custom objects... all you need to do is reference them in the code behind, and then bind to them in the XAML. This creates the code generation objects it needs.
For example, I have a viewmodel, CustomerViewModel that is bound in XAML. That viewmodel also has a property of type IGuest. In order to use the guest object and have it update properly, I came up with this in the code behind...
CustomerViewModel vm
{
get
{
return (CustomerViewModel)DataContext;
}
}
IGuest g
{
get
{
return vm.CurrentGuest;
}
}
public CartGuestControl()
{
this.InitializeComponent();
}
You don't need to assign any of the UI data contexts from the code behind... simply reference the datacontext that is bound in XAML. When binding to any straight viewmodel properties, I use {x:Bind Path=vm.IsEditing, Mode=OneWay}. For binding to any of the guest properties, it looks like this, {x:Bind Path=g.FirstName, Mode=TwoWay}. You could do something like this for your Player object.
I have run into times where x:Bind simply won't do what I expect it to do no matter what I try. This can usually be solved by breaking things out into smaller user controls with more specific data contexts or by using "regular" Binding.
So, I have an UserControl which is basically a Grid with 3 different DataGrids and some Labels. Seeing how I need to use this 3 times, instead of copying and pasting the code, I thought I'd just generate it once and use it in my main window.
I have defined the UserControl as:
<UserControl x:Class="Propuestas.UI.Andrei.DGMTX"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Propuestas.UI.Andrei"
mc:Ignorable="d"
Height="300"
Width="791.496">
And I am using it in my window as such:
<StackPanel Grid.Row="2">
<local:DGMTX/>
<local:DGMTX/>
<local:DGMTX/>
</StackPanel>
For some reason, it doesn't show up in the designer panel on my main window. Is there something I'm doing wrong?
Also, I would like to be able to bind based on a bound element. For example, let's say I have a class Model which has all the data that I need to represent in my UserControl.
I would like to do something like
<local:DGMTX Binding = {Binding Model}/>
and then be able to bind all of the other elements in my UserControl in its code. Is there a way I could do this in XAML? Or do I have to do it programmatically?
There are two ways to communicate your view model to controls:
As one commenter suggested, bind your view model to the data context of the user control. This enables binding everything in your view model to the inner workings of the control. Problem is the inner workings now depend on the data the object is associated with.
Create dependency properties for only the ones in your view model that the user control actually needs. I personally prefer this over the first in almost 99% of all cases because you know exactly what data the control expects and you can manipulate bound data in ways unique to the control that maybe the view model isn't responsible for.
Couple things to note about designer support when creating your own controls:
Visual Studio's designer still has a lot of issues when it comes to WPF. Don't believe me? Try referencing a dynamic resource defined in your main assembly in another. The designer will crash and tell you it can't be found. This isn't the actual case, however. As soon as you run the app, you will never see this exception.
In order to see changes made to source reflect in designer, you have to build the project first (the project in which the control resides, not necessarily the one it's referenced in). Sometimes, "cleaning" or (with better luck in some cases) "rebuilding" the project is the only thing that updates the designer in the main project when "building" doesn't work.
If after considering the latter and you still can't see anything, consider the implementation of the control. Is anything out of place? Did something accidentally get hidden? You may not think so at first and maybe it takes ten hours of frustration to succumb and check, but the little things can make all the difference.
Sometimes it seems that the Name and x:Name attributes are interchangeable.
So, what are the definitive differences between them, and when is it preferable to use one over the other?
Are there any performance or memory implications to using them the wrong way?
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 is 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.
They are not the same thing.
x:Name is a xaml concept, used mainly to reference elements. When you give an element the x:Name xaml attribute, "the specified x:Name becomes the name of a field that is created in the underlying code when xaml is processed, and that field holds a reference to the object." (MSDN) So, it's a designer-generated field, which has internal access by default.
Name is the existing string property of a FrameworkElement, listed as any other wpf element property in the form of a xaml attribute.
As a consequence, this also means x:Name can be used on a wider range of objects. This is a technique to enable anything in xaml to be referenced by a given name.
x:Name and Name are referencing different namespaces.
x:name is a reference to the x namespace defined by default at the top of the Xaml file.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Just saying Name uses the default below namespace.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
x:Name is saying use the namespace that has the x alias. x is the default and most people leave it but you can change it to whatever you like
xmlns:foo="http://schemas.microsoft.com/winfx/2006/xaml"
so your reference would be foo:name
Define and Use Namespaces in WPF
OK lets look at this a different way. Say you drag and drop an button onto your Xaml page. You can reference this 2 ways x:name and name. All xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" and
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" are is references to multiple namespaces. Since xaml holds the Control namespace(not 100% on that) and presentation holds the FrameworkElement AND the Button class has a inheritance pattern of:
Button : ButtonBase
ButtonBase : ContentControl, ICommandSource
ContentControl : Control, IAddChild
Control : FrameworkElement
FrameworkElement : UIElement, IFrameworkInputElement,
IInputElement, ISupportInitialize, IHaveResources
So as one would expect anything that inherits from FrameworkElement would have access to all its public attributes. so in the case of Button it is getting its Name attribute from FrameworkElement, at the very top of the hierarchy tree. So you can say x:Name or Name and they will both be accessing the getter/setter from the FrameworkElement.
MSDN Reference
WPF defines a CLR attribute that is consumed by XAML processors in order to map multiple CLR namespaces to a single XML namespace. The XmlnsDefinitionAttribute attribute is placed at the assembly level in the source code that produces the assembly. The WPF assembly source code uses this attribute to map the various common namespaces, such as System.Windows and System.Windows.Controls, to the http://schemas.microsoft.com/winfx/2006/xaml/presentation namespace.
So the assembly attributes will look something like:
PresentationFramework.dll - XmlnsDefinitionAttribute:
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Data")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Navigation")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Shapes")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Documents")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Controls")]
They're both the same thing, a lot of framework elements expose a name property themselves, but for those that don't you can use x:name - I usually just stick with x:name because it works for everything.
Controls can expose name themselves as a Dependency Property if they want to (because they need to use that Dependency Property internally), or they can choose not to.
More details in msdn here and here:
Some WPF framework-level applications
might be able to avoid any use of the
x:Name attribute, because the Name
dependency property as specified
within the WPF namespace for several
of the important base classes such as
FrameworkElement/FrameworkContentElement
satisfies this same purpose. There are
still some common XAML and framework
scenarios where code access to an
element with no Name property is
necessary, most notably in certain
animation and storyboard support
classes. For instance, you should
specify x:Name on timelines and
transforms created in XAML, if you
intend to reference them from code.
If Name is available as a property on
the class, Name and x:Name can be used
interchangeably as attributes, but an
error will result if both are
specified on the same element.
X:Name can cause memory issues if you have custom controls. It will keep a memory location for the NameScope entry.
I say never use x:Name unless you have to.
Name:
can be used only for descendants of FrameworkElement and FrameworkContentElement;
can be set from code-behind via SetValue() and property-like.
x:Name:
can be used for almost all XAML elements;
can NOT be set from
code-behind via SetValue(); it can only be set using attribute
syntax on objects because it is a directive.
Using both directives in XAML for one FrameworkElement or FrameworkContentElement will cause an exception: if the XAML is markup compiled, the exception will occur on the markup compile, otherwise it occurs on load.
The only difference is that if you are using user Controls into a control from Same Assembly then Name will not identify your control and you will get an error " Use x:Name for controls in the same Assembly".
So x:Name is the WPF versioning of naming controls in WPF. Name is just used as a Winform Legacy. They wanted to differentiate the naming of controls in WPF and winforms as they use attributes in Xaml to identify controls from other assemblies they used x: for Names of control.
Just keep in mind dont put a name for a control just for the sake of keeping it as it resides in memory as a blank and it will give you a warning that Name has been applied for a control buts its never used.
x:Name means: create a field in the code behind to hold a reference to this object.
Name means: set the name property of this object.
I always use the x:Name variant.
I have no idea if this affects any performance, I just find it easier for the following reason.
If you have your own usercontrols that reside in another assembly just the "Name" property won't always suffice. This makes it easier to just stick too the x:Name property.
It's not a WPF item but a standard XML one and BtBh has correctly answered it, x refers to the default namespace. In XML when you do not prefix an element/attribute with a namespace it assumes you want the default namespace.
So typing just Name is nothing more than a short hand for x:Name. More details on XML namespaces can be found at link text
The specified x:Name becomes the name of a field that is created in the underlying code when XAML is processed, and that field holds a reference to the object. In Silverlight, using the managed API, the process of creating this field is performed by the MSBuild target steps, which also are responsible for joining the partial classes for a XAML file and its code-behind. This behavior is not necessarily XAML-language specified; it is the particular implementation that Silverlight applies to use x:Name in its programming and application models.
Read More on MSDN...
When you declare a Button element in XAML you are referring to a class defined in windows run time called Button.
Button has many attribute such as background, text, margin, ..... and an attribute called Name.
Now when you declare a Button in XAML is like creating an anonymous object that happened to have an attribute called Name.
In general you can not refer to an anonymous object, but in WPF framework XAML processor enables you to refer to that object by whatever value you have given to Name attribute.
So far so good.
Another way to create an object is create a named object instead of anonymous object. In this case XAML namespace has an attribute for an object called Name (and since it is in XAML name space thus have X:) that you may set so you can identify your object and refer to it.
Conclusion:
Name is an attribute of a specific object, but X:Name is one attribute of that object (there is a class that defines a general object).
One of the answers is that x:name is to be used inside different program languages such as c# and name is to be used for the framework. Honestly that is what it sounds like to me.
My research is x:Name as global variable. However, Name as local variable. Does that mean x:Name you can call it anywhere in your XAML file but Name is not.
Example:
<StackPanel>
<TextBlock Text="{Binding Path=Content, ElementName=btn}" />
<Button Content="Example" Name="btn" />
</StackPanel>
<TextBlock Text="{Binding Path=Content, ElementName=btn}" />
You can't Binding property Content of Button with Name is "btn" because it outside StackPanel
Name can also be set using property element syntax with inner text, but that is uncommon. In contrast, x:Name cannot be set in XAML property element syntax, or in code using SetValue; it can only be set using attribute syntax on objects because it is a directive.
If Name is available as a property on the class, Name and x:Name can be used interchangeably as attributes, but a parse exception will result if both are specified on the same element. If the XAML is markup compiled, the exception will occur on the markup compile, otherwise it occurs on load.
Well, i must admit, still sometimes XAML seems a bit mysterious to me. The thing is, i always liked to debug through the C# code (setting lots of breakpoints in them) to get the idea of "what is happening" and "how is it happening". But with declarative XAML syntax that's not an option. I think you'll agree that to work with XAML, or to be precise, to work with/understand some existing XAML code you got to "already know" how things work with XAML declaration. There is just no way you can know/learn things investigating the execution of your application code. So i'm more than interested to take a look through XAML inside-out, as detailed as possible. I'm NOT talking about "learning" XAML, I know the basic stuff. May be i can provide some examples to clarify the sort of things i'm looking for -
Compared to C# code how an object gets instantiated when we use them in XMAL? Are they stored in managed heap? Same way as C# code-instantiated objects?
How the properties get set while using Mark-Up Extension syntax for Data/Command Binding?
When any property of an INotifyPropertyChanged type gets updated, how the Binding instatnce inside the XAML syntax updates the itself? How exactly it gets notified it at the first place, & by whom?
A viewmodel can be set as the DataContext of a view at runtime by defining Typed DataTemplate, like -
<DataTemplate DataType="{x:Type viewmodels:AccountsViewModel}">
<views:Accounts/>
</DataTemplate>
How does it happen actually? What are the rules for setting DataContext other than searching for the DataContext property upward the logical tree?
How the whole template things (DataTemplate, ControlTemplate & ItemsPanelTemplate) are treated/resolved at run time.
etc. etc. etc.
So if you are good/experienced/expert in XAML what would you suggest (links, articles, blogposts, books whatever) as reference that helps getting clear & deeper understanding about how XAML works "under-the-hood"? Thanks in advance.
Most can be explained by don't thinking of XAML as a real programming language, more like a declarative language. Everything you do in xaml, can be made in C# aswell, and in fact this is whats happening.
Compared to C# code how an object gets instantiated when we use them
in XMAL? Are they stored in managed heap? Same way as C#
code-instantiated objects?
Yes because they are just c# objects. Most resources are stored in a hibernated state, i rememberd the word inflated somewhere. Converter or other "direct" c# objects are created when they are needed. Important here is that these resources are usually shared, so they will get created only once.
How the properties get set while using Mark-Up Extension syntax for Data/Command Binding?
This again depends on where you use the markup extension. In a Style? In a Template? In a instanced user control like a window? Usually they are evaluated when you actually need them. It wouldn't make sense to evaluate them, when the inflated style is stored in the actual resource dictionary. They get evaluated when you actually use the style on an object.
When any property of an INotifyPropertyChanged type gets updated, how
the Binding instatnce inside the XAML syntax updates the itself? How
exactly it gets notified it at the first place, & by whom?
By the binding engine. WPF checks if your DataContext inherits the INotifyPropertyChanged interface, attaches to the event provided by the interface and listens to any changes. If such an event is raised, the binding engine will just call the getter again.
How does it happen actually? What are the rules for setting DataContext
other than searching for the DataContext property upward
the logical tree?
In short: None other. Datacontext is simply an inherited attached property. If you don't re set it on a child control, it will take the value the parent has until it reached the root. The only exception to this are ContentControls and ContentPresenter they will not inherit the DataContext but will change them depending on the content. So these controls always have by default the Content as their DataContext.
How the whole template things (DataTemplate, ControlTemplate & ItemsPanelTemplate) are treated/resolved at run time.
Simply spoken: Everytime WPF finds a non ui object, it tries to find a DataTemplate for the given type. In an ItemsControl for example: You can bind a list of MyClass; unless you provide an explicit DataTemplate or DataTemplateSelector it will search the resource tree upwards for an implicit style. Again remember that this already does not happen in XAML, but on the C# objects that was generated out of the xaml.
And is it by any means possible (at present or near future) to debug
through XAML code?
How do you think you can debug something that is not executed, but evaluated on compile time?
Please don't take this as 100% correct. Over the Years this is what i gathered of informations about XAML and the usage. If you have any corrections or find something that is clearly wrong. Please tell me, we are all here to learn and i always learn new things about the stuff i use :)
i wonder if there is a way to access a control's templatepart from within c# for modifying the part (e.g. hiding, etc..). is it possible to get a reference to the part with pure c#?
i don't want to touch the controls template.
thanks
j.
It is possible, but its quite nasty.
On the Template there is a method called FindName, which needs two arguments: the name and the FrameworkElement that has the ControlTemplate as Template. Of course, you need to set the name of the element in the ControlTemplate...
Another more elegent solution is to use a Binding in the ControlTemplate to determine the visibility.. That way you do not need to do stuff in your code behind and you can keep it Xaml only...