I'm creating a simple User Control in WPF that contains a TextBlock inside a Button.
<UserControl x:Class="WpfExpansion.MyButton"..... >
<Grid >
<Button Background="Transparent" >
<TextBlock Text="{Binding Path=Text}"/>
</Button>
</Grid>
</UserControl>
And also the "Text" dependency property.
public partial class MyButton : UserControl
{
public MyButton()
{
InitializeComponent();
this.DataContext = this;
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(MyButton), new PropertyMetadata(string.Empty));
}
And then I use the UserControl like this:
<MyButton Text="Test" />
The problem is that the Visual Studio design does not change, but it works in runtime.
What is wrong?
I also tried
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Inside the UC definition, without success.
Arguably the biggest feature of a dependency property is its built-in ability to provide change notification. The motivation for adding such intelligence to properties is to enable rich functionality directly from declarative markup.
A dependency property can reference a value through data binding. Data binding works through a specific markup extension syntax in XAML, or the Binding object in code. With data binding, determination of the final property value is deferred until run time, at which time the value is obtained from a data source.
Try using FrameworkPropertyMetadata
instead of PropertyMetadata
, specifying AffectsRender
like below, then restart Visual Studio:
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(MyButton),
new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.AffectsRender));
MSDN Documentation about FrameworkPropertyMetadataOptions.AffectsRender
says
Some aspect of rendering or layout composition (other than measure or arrange) is affected by value changes to this dependency property.
For other cases, there are options like AffectsMeasure, AffectsArrange, etc.
Golden shovel candidate, still I came across the same problem and had it solved being inspired by https://www.codeproject.com/Questions/1096567/How-to-set-a-custom-dependency-property-of-user-co
Long story short: your dependency property is set on the UserControl
itself and you are trying to bind the it's child property to it. The child's binding needs to have RelativeSource
defined, hence the TextBlock
should look like this:
<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=Text}" />
The only DataContext
assignment needed is the one you already have in the code behind in the constructor.
DataContext
in XAML already, you don't need to provide it in each of the controls. This means you need to define your UC the following way (d:DataContext=...
does the trick):
<UserControl x:Class="WpfExpansion.MyButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:YRS100_Data_Analysis"
mc:Ignorable="d"
d:DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Button Background="Transparent">
<TextBlock Text="{Binding Path=Text}" />
</Button>
</Grid>
</UserControl>
Works like a charm.
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