1

I need to bind the text box with the data available on it and execute a command associate with that. I want the data entered as well command execution only when "Enter" button on keyboard is pressed. I used to the below code, but it seems, I am getting command execution without "Enter" is pressed also found that for each number or text pressed, I am getting the command. I don't want this to happen.

my InputDataTemplate.xaml code:

<Label Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Content="{Binding Name}" />
<Label Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Center" Content="{Binding Value}" />
<TextBox Grid.Column="1" Width="60" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Data}" DataContext="{Binding}" >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="TextChanged" >
                        <ei:CallMethodAction TargetObject="{Binding}" MethodName="IpDataTrig" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>

I can understand EventName="TextChanged" plays a role here. But not sure about the other stuffs.

My TesterView.xaml code:

<UserControl.Resources>
    <DataTemplate x:Key="InputDataTemplate" >
        <local:InputDataTemplate DataContext="{Binding}" />
    </DataTemplate>
</UserControl.Resources>

<Grid Grid.Row="2" Background="AliceBlue" >
    <Label Content="Input Datas" FontWeight="Bold"
               HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<Border Grid.Row="3" BorderBrush="Black" BorderThickness="0,2,0,0" >
    <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled" >
        <ItemsControl x:Name="IpDataNames" 
                      DataContext="{Binding }"
                      ItemsSource="{Binding IpDataNames}"
                      ItemTemplate="{DynamicResource InputDataTemplate}" />
    </ScrollViewer>
</Border>

my TesterViewModel.cs:

private ObservableCollection<InputDataService> _IpDataNames;
private InputDataService l_IpDataNames;

 _IpDataNames = new ObservableCollection<InputDataService>();

public ObservableCollection<InputDataService> IpDataNames
        {
            get { return _IpDataNames; }
            set
            {
                IpDataNames = value;
            }
        }

InputDataService.cs:

public class InputDataService : BindableBase
    {
        public string Name { get; set; }
        public string Value { get; set; }
        public string Data { get; set; }

        public void IpDataTrig()
        {
            Debug.WriteLine(string.Format("\nInput Data {0} Updated : {1} : {2}", Name, Data, Value));
        }
    }
yuvi
  • 25
  • 8

1 Answers1

1

Possible duplicate question: https://stackoverflow.com/a/10466285/475727

BTW, nothing is wrong about capturing KeyPress event and calling command from codebehind. It is not violation of MVVM pattern.

Sometimes I use my own behavior implemented as attached property. Big advantage is, that I can use it in styles. This behaviour update binding source on text property and then calls command. (TextBox.Text binding is updated on losf focus by default)

public static class TextBoxBehaviour
{
    public static readonly DependencyProperty CommandOnEnterPressedProperty = DependencyProperty.RegisterAttached("CommandOnEnterPressed",typeof (ICommand),typeof (TextBoxBehaviour),
            new FrameworkPropertyMetadata(CommandOnEnterPressedPropertyChanged));

    private static void CommandOnEnterPressedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var sender = (TextBox) d;
        sender.KeyDown -= OnKeyDown;

        if (e.NewValue is ICommand)
        {
            sender.KeyDown += OnKeyDown;
        }
    }

    private static void OnKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            var tbx = (TextBox) sender;
            var textBindigExpression = tbx.GetBindingExpression(TextBox.TextProperty);
            if (textBindigExpression != null)
            {
                textBindigExpression.UpdateSource();
            }
            var command = GetCommandOnEnterPressed(tbx);
            if (command.CanExecute(null)) command.Execute(null);
        }
    }

    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static void SetCommandOnEnterPressed(TextBox elementName, ICommand value)
    {
        elementName.SetValue(CommandOnEnterPressedProperty, value);
    }

    public static ICommand GetCommandOnEnterPressed(TextBox elementName)
    {
        return (ICommand) elementName.GetValue(CommandOnEnterPressedProperty);
    }
}

and usage

<TextBox Text="{Binding SearchTerm, UpdateSourceTrigger=Explicit}" 
         my:TextBoxBehaviour.CommandOnEnterPressed="{Binding SearchCommand}"/>
Community
  • 1
  • 1
Liero
  • 25,216
  • 29
  • 151
  • 297
  • The KeyBinding solution from the linked duplicate question is my preferred way of doing this. It's *really* simple and requires minimal work to get your head around. Being able to set the above answer in a Style would be great if you have a large number of identical controls to manage. – goobering Mar 11 '15 at 13:45