0

I am building a WPF Custom Control (Note: NOT a user control). The c# code for the control is defined as follows:

using System.Windows;
using System.Windows.Controls;
using MvvmFoundation.Wpf;

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

        public AutoComp()
        {
            DownCommand = new RelayCommand(() =>
            {
                System.Diagnostics.Debug.WriteLine("Down");
            });
            PressedCommand = new RelayCommand(() =>
            {
                System.Diagnostics.Debug.WriteLine("Pressed");
            });
        }

        public RelayCommand DownCommand
        {
            get { return (RelayCommand)GetValue(DownCommandProperty); }
            set { SetValue(DownCommandProperty, value); }
        }

        public static readonly DependencyProperty DownCommandProperty =
            DependencyProperty.Register("DownCommand", typeof(RelayCommand), typeof(AutoComp), new PropertyMetadata(null));

        public RelayCommand PressedCommand
        {
            get { return (RelayCommand)GetValue(PressedCommandProperty); }
            set { SetValue(PressedCommandProperty, value); }
        }

        public static readonly DependencyProperty PressedCommandProperty =
            DependencyProperty.Register("PressedCommand", typeof(RelayCommand), typeof(AutoComp), new PropertyMetadata(null));
    }
}

I define the template for the control in Generic.xaml as follows:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TextBoxWithInputBinding">
    <Style TargetType="{x:Type local:AutoComp}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:AutoComp}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            >
                        <StackPanel>
                            <TextBox>
                                <TextBox.InputBindings>
                                    <KeyBinding Key="Down" Command="{TemplateBinding DownCommand}"/>
                                </TextBox.InputBindings>
                            </TextBox>
                            <Button Content="Press me" Command="{TemplateBinding PressedCommand}"/>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

When I press the "Press me" button the PressedCommand is triggered (the word "Pressed" appears in the output window - however, when I type in the TextBox and press the down key, nothing happens.

What do I need to do to make the DownCommand fire?

2
  • You should check this entry; stackoverflow.com/questions/26686248/… Commented Feb 25, 2017 at 21:09
  • @orhun.begendi Thanks, but if you look at my code, that is what I am already doing. Commented Feb 25, 2017 at 21:37

2 Answers 2

1

As you have already discovered you should replace the TemplateBinding with the usual binding markup and use a {RelativeSource TemplatedParent}

<KeyBinding Key="Down"
    Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DownCommand}"/>

I would still like to know why the Button binding works with TemplateBinding but the TextBox KeyBinding does not?

Because TemplateBinding is optimized and has some limitations compared to using an ordinary Binding. For example it only works directly inside the ControlTemplates's visual tree but not in DataTriggers and KeyBindings.

You will find more information about this here:

WPF TemplateBinding vs RelativeSource TemplatedParent

Sign up to request clarification or add additional context in comments.

Comments

0

So I found the answer: I need regular Binding not TemplateBinding: I replaced

<KeyBinding Key="Down" Command="{TemplateBinding DownCommand}"/>

with

<KeyBinding Key="Down"
    Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DownCommand}"/>

I would still like to know why the Button binding works with TemplateBinding but the TextBox KeyBinding does not!!!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.