Having the xaml below in MainWindow.xaml:
<Window x:Class="TestDependency.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"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Label Name="someLabel" Grid.Row="0" Content="{Binding Path=LabelText}"></Label>
<Button Grid.Row="2" Click="Button_Click">Change</Button>
</Grid>
</Window>
And the following code behind in MainWindow.xaml.cs:
public static readonly DependencyProperty LabelTextProperty = DependencyProperty.Register("LabelText", typeof(String), typeof(MainWindow));
public int counter = 0;
public String LabelText
{
get
{
return (String)GetValue(LabelTextProperty);
}
set
{
SetValue(LabelTextProperty, value);
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
LabelText = "Counter " + counter++;
}
I would have thought that the default DataContext
is the code behind. But I'm forced to specify the DataContext
. Which DataContext
is the default? Null
? I would have thought that the code behind would have been (as is the same class).
And as in this sample I'm using the code behind to modify the content of the Label, could I use directly:
someLabel.Content = "Counter " + counter++;
I will expect that being the code behind, it shouldn't have the UI update problem that you have if the DataContext
is in a different class.
The DataContext is the source of all entities mapped over a database connection. It tracks changes that you made to all retrieved entities and maintains an "identity cache" that guarantees that entities retrieved more than one time are represented by using the same object instance.
The DataContext property is the default source of your bindings, unless you specifically declare another source, like we did in the previous chapter with the ElementName property. It's defined on the FrameworkElement class, which most UI controls, including the WPF Window, inherits from.
A binding source is usually a property on an object so you need to provide both the data source object and the data source property in your binding XAML. In the above example the ElementName attribute signifies that you want data from another element on the page and the Path signifies the appropriate property.
Yes, the default value of DataContext
is null
, here is how it's declared in FrameworkElement
class -
public static readonly DependencyProperty DataContextProperty =
DependencyProperty.Register("DataContext", typeof(object),
FrameworkElement._typeofThis,
(PropertyMetadata) new FrameworkPropertyMetadata((object)null,
FrameworkPropertyMetadataOptions.Inherits,
new PropertyChangedCallback(FrameworkElement.OnDataContextChanged)));
FrameworkPropertyMetadata
takes first param for default Value of property.
As it gets inherited by all the child controls your lable's DataContext
remains null
unless you specify the window data context.
and you can use someLabel.Content = "Counter " + counter++;
in codebehind to set labels content; as such it's perfectly fine to access your controls in code behind.
Since you are binding a property of a Label
, unless you specify a different binding source somehow the binding engine assumes that LabelText
is a property on that class. It cannot magically determine that because the Label
is a descendant of a MainWindow
the binding source should be that window, which is why you need to explicitly declare it.
It's important to note that the concepts of "data context" and "binding source" are distinct: DataContext
is one way to specify the binding source, but there are also others.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With