Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use TwoWay binding from within a UserControl?

I have my own UserControl, a LabeledTextBox which is the combination of a Label and a..well, TextBox. This Control has two properties: Caption which will be bound to the caption of the Label, and Value which will be bound to the Text of the TextBox.

Code:

public class LabeledTextBox : Control
{
    static LabeledTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(LabeledTextBox), new FrameworkPropertyMetadata(typeof(LabeledTextBox)));
    }

    public string Caption
    {
        get { return (string)GetValue(CaptionProperty); }
        set { SetValue(CaptionProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Caption.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CaptionProperty =
        DependencyProperty.Register("Caption", typeof(string), typeof(LabeledTextBox), new UIPropertyMetadata(""));


    public string Value
    {
        get { return (string)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(string), typeof(LabeledTextBox), new UIPropertyMetadata(""));


}

XAML:

<Style TargetType="{x:Type local:LabeledTextBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:LabeledTextBox}">
                <Grid>
                    <Grid>

                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <Label Grid.Row="0" Content="{TemplateBinding Caption}" />
                    <TextBox  Name="Box" Margin="3,0,3,3" Grid.Row="1" Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />

                    </Grid>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Usage:

<uc:LabeledTextBox Caption="Code:" Value="{Binding ExpenseCode}"  />

Initially I thought I had found my answer here: WPF TemplateBinding vs RelativeSource TemplatedParent

That details the difference between TemplateBinding and RelativeSource TemplatedParent. I've changed my code accordingly, but it still feels like I'm missing a step. The OneWay binding does work, my textbox is bound to the Value property, but changes do not register.

How do I get this to work?

like image 281
diggingforfire Avatar asked Apr 20 '12 09:04

diggingforfire


2 Answers

Change the mode here.

<uc:LabeledTextBox Caption="Code:" Value="{Binding ExpenseCode,Mode=TwoWay}"  /> 

it worked at my end

like image 186
Akanksha Gaur Avatar answered Sep 29 '22 09:09

Akanksha Gaur


Just in case anybody has this problem:

Another approach (maybe more elegant) would be to declare the dependency property of the usercontrol in a way so that it defaults to two way binding (e.g. as the framework TextBox does by default).

This can be achieved as follows (taken from the answer of this Stackoverflow question):

    public DependencyProperty SomeProperty =
        DependencyProperty.Register("Some", typeof(bool), typeof(Window1),
            new FrameworkPropertyMetadata(default(bool),
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

The key here is using FrameworkPropertyMetadata.

like image 44
me. Avatar answered Sep 29 '22 07:09

me.