According to my understanding, setting the DataContext
to a control itself will allow you to access the property of that control using data binding without specifying the Source
, so setting the DataContext
of a Window
to {Binding RelativeSource={RelativeSource Self}}
should only allow you to data bind to the properties defined in the Window
class, not the ones in the code-behind because the code-behind file only inherited the Window
class, and the properties I defined in the code-behind file don't directly belong to the Window
class. However, when I do it, it magically allows me to data bind to the properties I defined in the code-behind file. How does this work?
CodePudding user response:
Yes, setting the DataContext
of a control to itself allows you to access its properties in a Binding
.
Code-Behind
public MyWindow() { DataContext = this; InitializeComponent(); }
Creating a
Binding
in XAML will automatically inherit thisDataContext
asSource
for binding if it is not overridden e.g. an item is set asDataContext
in anItemsControl
.Data context is a concept that allows elements to inherit information from their parent elements about the data source that is used for binding, as well as other characteristics of the binding, such as the path. [...]
XAML
<Window 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" x:Class="MyWpfApp.MyWindow" ... DataContext="{Binding RelativeSource={RelativeSource Self}}">
The
RelativeSource
will set theSource
of theBinding
to the window itself. The same would be true, if you would useAncestorType={x:Type Window}
.Gets or sets the binding source by specifying its location relative to the position of the binding target.
You cannot set multiple different sources on a single binding.
RelativeSource
: mutually exclusive versus withElementName
andSource
;
In essence, the you never bind without setting a Source
, it is set implicitly or explicitly.
Why does the Binding
work then, if you specify a Window
as source? You have to understand, that the XAML file and your code-behind are one and the same class after compilation. They are both partial
definitions that are merged on compilation. You are right that you inherit from Window
, but your understanding of bindings is wrong. If we talk about class inheritance, you are right, accessing a derived MyWindow
through a Window
reference would not allow you to access its properties, but bindings do not work this way. They are expressions that loosley couple dependency properties to properties being bound. They are only resolved at run-time, which means they are applied to the actual run-time type of the DataContext
, which is MyWindow
.
Defers a property value to be a data-bound value, creating an intermediate expression object and interpreting the data context that applies to the element and its binding at run time.
You could assign and switch any arbitrary object
as DataContext
even of different types. As long as the Path
of any binding matches any property value it will be resolved successfully, otherwise there will be a binding error.