What is DataContext in XAML? - xaml

Please describe what is DataContext in XAML and when use it and relationship between {Binding} syntax. (with example) (In simple terms)
Thank you a lot.

Data contexts are described within the Microsoft documentation here.
A datacontext is data accessible to (aka within scope of) the current element. Thus a TextBox might have a datacontext set to SomeObject. If you where to bind to this using a binding, like this:
<TextBox DataContext={binding Path=SomeObject} Text={Binding Path=MyString} />
the textbox would have a datacontext containing the values in SomeObject. Any binding performed on this element (or any nested elements) will be within this scope. So, the binding on the 'text' dependency property would try to find the value in SomeObject.MyString.
It's important to note that the data context is passed down to its child elements: if a datacontext is set on a parent and you do not explicitly override this on its child elements, then the children will also have the same data context.

Related

UWP MVVM XAML Dynamic UserControl Manager

I need help with a change of perspective.
I got stuck trying to approach UWP in a way I used to do in WPF regarding a MVVM pattern for managing UserControls dynamically.
I naturally tried to perform the same pattern in UWP but got stuck on various things like UWP not supporting 'x:Type' ...
Situation is; time to rethink this approach and look for a new direction. Seems I'm forced to abandon to use implicit binding in a similar fashion to the WPF pattern, using the Content property of a ContentPresenter and a VM property 'of type Object', which maintain a selected ViewModel. It was a simple and clean approach for matching up the correct View automagically with the VM set in ActiveViewModel.
the below was such a simple way of managing many views all over the place, odd MS not fixing this? But, back to the big Q: what now in UWP!?
<ContentPresenter Content="{Binding ActiveViewModel}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:OneViewModel}">
<local:OneView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:TwoViewModel}">
<local:TwoView />
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
What Shall I do instead of this!? Anyone found a new efficient way of doing it? I got stuck in my stubborn mind and need someone to kick my butt so I go forward. Getting to old to change, but due to this profession it seems I constantly have to. :)
Looking at the DataTemplate documentation, there's a paragraph explaining the situation which you are trying to figure out.
For advanced data binding scenarios, you might want to have properties
of the data determine which template should produce their UI
representations. For this scenario, you can use a DataTemplateSelector
and set properties such as ItemTemplateSelector to assign it to a data
view. A DataTemplateSelector is a logic class you write yourself,
which has a method that returns exactly one DataTemplate to the
binding engine based on your own logic interacting with your data. For
more info, see Data binding in depth.
Here, you have an example on how you can select distinct DataTemplate for items in a control such as a ListView based on defined conditions.
Your situation is a bit different from the one described above, but the solution should be within what is explained above.
Create a class which derives from DataTemplateSelector, and override the SelectTemplateCore methods exposed by it, where you define the logic of what DataTemplate should be selected for the specific presented object.
This Derived class should expose properties of type DataTemplate, which identify each single DataTemplate template object, you pretend to be able to choose from.
Just as in the example, you are probably better of by defining the DataTemplate resources on an higher level object, such as the Page itself.
Instantiate your DataTemplateSelector Derived class in XAML as a resource and set each of the properties exposed above of type DataTemplate to the analogous DataTemplate static resource.
Utilize the ContentTemplateSelector dependency property, by setting it your custom DataTemplateSelector.
With this logic, it should be possible to have your ContentPresenter decide correctly between which DataTemplate it should choose from, based on your required UI logic.

In static method bindings that exist inside DataTemplates, is it possible to pass in the instance of the entity?

Example:
<DataTemplate x:DataType="FooEntity">
<Grid Background="{x:Bind MyClass.MyStaticBindingMethod(???)}" />
</DataTemplate>
It’s easy enough to pass in properties of the entity, but I can’t see a way to pass in the instance itself. Is this feature not supported? I could store a reference to this in FooEntity with a property called Instance (for example), and then go MyClass.MyStaticBindingMethod(Instance), but just want to make sure there isn't a cleaner way.
Relevant docs: https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/x-bind-markup-extension
You cannot pass the instance itself onto a DataTemplate.
The DataTemplate is only responsible for describing the visual structure of a data object and therefore its not part of its job to hold a explicit reference to any CLR object.
DataTemplate is defined to extend the visual structure of data objects, such as GridView/ListView, and those already handle the possibility of referencing to Collections, by setting the ItemsSource dependency property. Taking advantage of this, the DataTemplate simply exposes the customization of your visual structure. However this visual structure should be followed with the necessary bindings, to achieve your desired custom behavior.
If you are dealing with x:Bind, you will have to set the x:DataType, to the type of the Collection which you are setting as the Control ItemsSource, because the compiler needs that information at compile-time.
That is not a problem for Binding because those are evaluated at runtime, with the help of reflection.
I am not sure if I understand correctly, but to bind this, meaning the entity directly, you can just use empty binding:
Background="{x:Bind}"
or
Background="{Binding}"
This however means that FooEntity should derive from Brush so that it is compatible with Background type.

Access UserControl child controls?

I have a custom UserControl. That control has a Grid which I can access by name. But I can't seem to access the subcontrols from UserControl's constructor.
I can do:
this.LayoutRoot
but not
this.LayoutRoot.MyChildControl
how can I access this control programmatically?
If you used the x:Name attribute: x:Name="MyChildControl", you cen refference it in code behind regardless of nesting.
x:Name sets the FrameworkElement.Name property (but can be also used on objects other then FrameworkElement) and results in creating a field with this name which is assigned to in InitializeComponent().
So you can call simply:
this.LayoutRoot...
this.MyChildControl...
Note that FrameworkElement has a FindName method, which will work similarly to what you expected:
this.LoayoutRoot.FindName("MyChildControl")
By code you can create new object of your UserControl and then you can easily access user control elements by it's name.
MyUserControl ctrl=new MyUserControl();
ctrl.LayoutGrid.Background=new SolidColorBrush(Colors.Blue);
or generally
ctrl.ChildrenName
UserControl's child control can access by UserControl.Content. If you want to access your Grid's children, please use this.LayoutRoot.Children. You can enumerate this collection.

How to get Control from DataTemplate and ControlTemplate ? thinks so much

When i define a control in DataTemplate, how to get reference of this control ?
If the control in ControlTemplate of Style , how to get ?
You should instead tell us why you would need to reference a control inside a template.
Consider that the control will be rendered multiple times, so getting a single reference does simply not make any sense.
The most common approach to this is to 'name' the element that you wish to locate via x:Name="MyElementName", you can then use the FindName method to locate the names element. If your DataTemplate is being used in an ItemsControl to render multiple copies of yoru XAML markup, then clearly there will be a number of elements that share this same name. For this reason, there is a concept known as XAML namescope, you should read up on this to understand the scope of the name you provide.
If you require a more generic method for searching for elements in the visual tree, try Linq-to-VisualTree, you can use it to query you UI, for example:
var itemsFluent = this.Descendants<TextBox>()
.Where(i => i.Ancestors().FirstOrDefault() is Grid);
The above query will find all TextBoxs that have a Grid as a direct parent.
Finally, if you can avoid doing any of this, by using databinding, or event bubbling then do so! it is much easier.

How can a custom type loaded through XAML obtain a reference to the root object

I am attempting to use XAML to represent and load a graph of custom types that form a semantic model for a business domain.
One thing I would like to do is to be able to obtain a reference to the "root object" of the graph from an object deeper in the tree. I cannot find any straightforward way of doing this other than resorting to barbarous practices like having the root object as a singleton.
Any ideas?
I don't know that this is a problem unique to XAML. All XAML is doing is instantiating your "child" objects and adding them to a collection property on the "parent" object. So if you had something like:
<my:Category Name="Products">
<my:Category.Subcategories>
<my:Category Name="Clothing" />
<my:Category Name="Jewellery" />
</my:Category.Subcategories>
</my:Category>
... then you'd end up with a "Products" category with two subcategories. It'd be up to you to code up your "Category" class in such a way that adding a subcategory saves a reference to the "owner" of that subcategory somewhere. I'd probably use a custom collection type (override the Add and Remove methods so that they set the "Parent" or "Owner" property on the object being added).