Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UserControl Dependency Property design time

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.

like image 727
Guilherme Avatar asked Aug 10 '13 03:08

Guilherme


People also ask

What is the biggest feature of dependency property?

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.

How does dependency property internally work?

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.


2 Answers

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.

like image 100
Nitesh Avatar answered Oct 31 '22 09:10

Nitesh


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.


UPDATE

But then I tried your attempts and came to the conclusion that if you define the 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.

like image 26
Mike Avatar answered Oct 31 '22 09:10

Mike