Linking Self / 'this' in XAML

A simple WPF / XAML question. In XAML, how can I refer to a Self / this object in this context? In a very basic application with a main window, one control, and a C # encoded property for the window, I want to bind the control property to the window’s manual encoding property.

In code, this is very simple - in the Window constructor, I added the following:

Binding bind = new Binding(); bind.Source = this; bind.Path = new PropertyPath("ButtonWidth"); button1.SetBinding(WidthProperty, bind); 

Obviously, I have a ButtonWidth property and a control called button1. I cannot figure out how to do this in XAML. Various attempts, like the following example, did not work:

 <Button x:Name="button1" Width="{Binding Source=Self Path=ButtonWidth}"/> <Button x:Name="button1" Width="{Binding RelativeSource={RelativeSource Self} Path=ButtonWidth}"/> 

etc.

thank

+46
c # wpf xaml
01 Oct '10 at 9:01
source share
5 answers

First use a comma between RelativeSource and Path in your binding:

 <Button x:Name="button1" Width="{Binding RelativeSource={RelativeSource Self}, Path=ButtonWidth}"/> 

Secondly, RelativeSource is attached to Button. A button does not have a ButtonWidth property. I assume you need to link your parental controls.

So try the RelativeSource binding:

 <Button x:Name="button1" Width="{Binding RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type YourNamespace:YourParentControl}}, Path=ButtonWidth}"/> 
+76
01 Oct '10 at 9:07
source share

I think you are looking for:

 <Window x:Class = "blah blah all the regular stuff" DataContext="{Binding RelativeSource={RelativeSource Self}}" > 
+29
Nov 07
source share

One of the ways I have to deal with RelativeSource and the like is with the root XAML element name:

 <Window x:Class="TestApp2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" x:Name="_this" > <Grid> <Button x:Name="button" Width="{Binding ElementName=_this,Path=ButtonWidth}" /> </Grid> </Window> 

If you want to set a DataContext, you can also do this:

 <Window x:Class="TestApp2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" x:Name="_this" > <Grid DataContext="{Binding ElementName=_this}"> <Button x:Name="button" Width="{Binding Path=ButtonWidth}" /> </Grid> </Window> 

I think this is a good trick to not remember all the complexities of RelativeSource binding.

+28
Nov 29 '10 at
source share

The problem with naming the XAML root element is that if you are used to using the same name (that is, "_this", "Root", etc.) for all the roots in your project, then late binding in the nested templates can access the wrong item. This is because when {Binding} ElementName=... used in Template , names are resolved at runtime by walking up the NameScope tree until the first is found.

The Clint solution avoids naming the root element, but it sets the root element in its own DataContext , which may not be available if the DataContext is needed, say, for data. It also seems a bit difficult to enter another binding to an element just to provide access to it. Later, if access is no longer needed, this {Binding} will become a mess: the responsibility for access properly belongs to the target and binding.

Accordingly, here is a simple markup extension for accessing the XAML root element without specifying its name:

 using System.Xaml; using System.Windows.Markup; public sealed class XamlRootExtension : MarkupExtension { public override Object ProvideValue(IServiceProvider sp) { var rop = sp.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider; return rop == null ? null : rop.RootObject; } }; 

XAML :

 <Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:global="clr-namespace:"> <TextBlock Text="{Binding Source={global:XamlRoot},Mode=OneTime}" /> </Window> 

note: for clarity, I did not define MarkupExtension in the namespace; using the empty alias clr-namespace as shown here, d̲o̲e̲s̲ actually works to access the global:: namespace global:: (although the VS2013 designer seems to complain about this).

Result :

enter image description here
A window whose contents are associated with itself.




N.B.

+4
Dec 19 '14 at 22:18
source share

Unfortunately, the name of the root element with "ElementName = .." seems to be the only way with UWP, since {RelativeSource Self} is not supported there.

Oddly enough, this still works when the name is redefined in the layout, for example.

 <UserControl x:Class="Path.MyClass" x:Name="internalName"> <Border Background={Binding Path=Background, ElementName=internalName}" ... 

then

 <Page> <local:MyClass x:Name=externalName /> </Page> 

By the way, Windows 10 fixed a bug (present in Windows 8.1) when the same internal name is used for different elements in the same layout.

However, I would prefer to use {RelativeSource Self}, as it looks more logical and safe for me.

0
Feb 15 '17 at 2:17
source share



All Articles