TemplateBinding not working for textbox text
Asked Answered
B

2

9

I have a custom control called EnhancedTextBox which is a UserControl that has a TextBox and a Button. To the consumer I want it to mostly look like a TextBox, so I did the following:

<UserControl.Template>
    <ControlTemplate TargetType="textBoxes:EnhancedTextBox">
    ...
    <TextBox Text="{TemplateBinding Text}"...

And in EnhancedTextBox I have

public static readonly DependencyProperty TextProperty =
  DependencyProperty.Register("Text", typeof (String), typeof (EnhancedTextBox));

public String Text
{
  get { return (String) GetValue(TextProperty); }
  set { SetValue(TextProperty, value); }
}

Yet, when I use it as the following:

<EnhancedTextBox Text="{Binding MyText, Mode=TwoWay, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}}" />

Then, MyText is never updated, as well as I inspect EnhancedTextBox.Text and it is null. What am I missing? I have been staring at this for a bit and can't figure out what is wrong. I even thought it might be the fact that I was using the same name, so create a property called Text1 which did not work....

Also of note, if I use a regular TextBox, then this all works. So, I am fairly certain the problem is with the EnhancedTextBox itself

Besiege answered 9/1, 2014 at 20:35 Comment(8)
Did you try <EnhancedTextBox Text={Binding MyText, Mode=TwoWay} />?Stempson
@Stempson Updated...sorry I guess I shortened it too muchBesiege
@Stempson I believe TextBox defaults to 2way binding anywayPolak
@Polak Also, updated...simply a typo in putting it into SOBesiege
@JustinPihony sure - looks OK to me sorry I can't help morePolak
Is the TextProperty actually needed? Can you not just have a regular property that the text box is bound to?Yunyunfei
@Andrew I need it to be a DependencyProperty so that it can be used in XAMLBesiege
@JustinPihony Fair enough. I thought I had done something like this before in XAML without it.Yunyunfei
B
26

I figured it out after reading this MSDN about TemplateBinding. Specifically,

A TemplateBinding is an optimized form of a Binding for template scenarios, analogous to a Binding constructed with {Binding RelativeSource={RelativeSource TemplatedParent}}.

So, I decided to do this explicitly...which would allow me to set the UpdateSourceTrigger (still not sure why it doesn't default to PropertyChanged)

<TextBox Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text, UpdateSourceTrigger=PropertyChanged}"....

And, now it is working. TemplateBinding does not even expose these properties....again, not sure why

Besiege answered 9/1, 2014 at 21:0 Comment(3)
Hey, today I too experienced the same issue and its working now with your solution but if both TemplateBinding Value the {Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value} are analogous then why is it accepting! If till now you've figured out and answer it would be kind of you to share here and update your answer. Thank You!Evacuation
There's no UpdateSourceTrigger on TemplateBinding because TemplateBinding is a one-way binding to the view. The MSDN link you posted states: A TemplateBinding is always a one-way binding, even if properties involved default to two-way binding. Not sure why they didn't allow two-way binding though.Cocktail
Old, but I struggled with this. Note that you can set the default bindings for your own dependency properties: #2664465 . In my case I had to use the binding above, with Mode=TwoWay and I'd also set the dependency property default binding to two way. Now binding to a textbox worked without also having to specify there that it had to be two way.Calycle
M
-1

You are missing the CallBack when you register the property.

Here's a sample code.

    public bool IsSelected
    {
        get { return (bool)GetValue(IsSelectedProperty); }
        set { SetValue(IsSelectedProperty, value); }
    }

    public void IsSelectedChangedCallback()
    {

        //actions when property changed

    }

    private static void OnSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        userControl.IsSelectedChangedCallback();
    }

    public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(MyUserControl), new PropertyMetadata(new PropertyChangedCallback(OnSelectedChanged)));
Microprint answered 9/1, 2014 at 21:0 Comment(1)
This is not it. The callback would get called, but the bound MyText property would still not get updated.Aesthetics

© 2022 - 2024 — McMap. All rights reserved.