zyash
zyash

Reputation: 732

Binding within a UserControl not working (templatebinding to a custom dependency property)

I have a user control which I'd like to be used like so:

// MainPage.xaml
<my:MyControl Data="10" />
<!-- or -->
<my:MyControl Data="{Binding SomeData}" />

It's codebind is this:

 public partial class MyControl : UserControl
 {
    public MyControl() {
       InitializeComponent();
    }
   public const string DataPropertyName = "Data";
   public int Data
        {
            get
            {
                return (int)GetValue(DataProperty);
            }
            set
            {
                SetValue(DataProperty, value);
            }
        }

        public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
            DataPropertyName,
            typeof(int),
            typeof(MyControl),
            new PropertyMetadata(10);
 }

It's xaml portion is this:

 <UserControl>
    <!-- omitted namespaces etc. -->
    <Grid x:Name="LayoutRoot">
         <Button x:Name="myButton" Content="{Binding Data}">
           <Button.Style>
             <Setter Property="Template">
               <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <TextBlock Text="{TemplateBinding Content}" />
                 </ControlTemplate>
                 </Setter.Value>
            </Button.Style>
         </Button>
    </Grid>
   </UserControl>

The crucial line, in usercontrol's xaml part is:

<Button x:Name="myButton" Content="{Binding Data}"> 

I'd like to bind this Button's Content property to the UserControl's property (Data), while still retaining the ability to set values on it from outside (<my:MyControl Data="10" />)

The problem is, that when I use binding - <Button x:Name="myButton" Content="{Binding Data}"> - it doesn't work (The templatebinding doesnt pick any values) It works however, if I set the values manually i.e - <Button x:Name="myButton" Content="12">

Upvotes: 3

Views: 1998

Answers (1)

nemesv
nemesv

Reputation: 139758

If you want to bind to your "own" dependency property inside a UserControl you need to add a x:Name to your UserControl and use it as the ElementName in your binding.

<UserControl x:Name="myControl">
    <!-- omitted namespaces etc. -->
    <Grid x:Name="LayoutRoot">
         <Button x:Name="myButton" 
                 Content="{Binding Data, ElementName=myControl}">        
         </Button>
    </Grid>
</UserControl>

To make the Template also work:

Instead of the TemplateBinding you need to use the RelativeSource TemplatedParent sysntax, because you need to set the Mode=OneWay (TemplateBinding uses Mode=OneTime for performance reasons by default but in your scenario you need Mode=OneWay)

<Style TargetType="Button">
    <Style.Setters>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <TextBlock Text="{Binding Path=Content, Mode=OneWay, 
                        RelativeSource={RelativeSource TemplatedParent}}" />
                </ControlTemplate>    
            </Setter.Value>
        </Setter>
    </Style.Setters>
</Style>

Upvotes: 6

Related Questions