带触发器的文本框绑定

时间:2015-03-11 08:19:47

标签: c# wpf data-binding textbox datatemplate

我需要将文本框与其上可用的数据绑定,然后执行与之关联的命令。我希望输入的数据以及命令执行仅在"输入"按下键盘上的按钮。我习惯了下面的代码,但似乎,我没有"输入"按下也发现对于按下的每个数字或文本,我都得到命令。我不希望这种情况发生。

我的InputDataTemplate.xaml代码:

<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>

我可以理解 EventName =&#34; TextChanged&#34; 在这里扮演一个角色。但不确定其他的东西。

我的TesterView.xaml代码:

<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>

我的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));
        }
    }

1 个答案:

答案 0 :(得分:1)

可能重复的问题:https://stackoverflow.com/a/10466285/475727

顺便说一下,从代码隐藏中捕获KeyPress事件和调用命令没什么不对。它不违反MVVM模式。

有时我使用自己的行为作为附加属性实现。最大的优点是,我可以在风格中使用它。 此行为更新文本属性上的绑定源,然后调用命令。 (TextBox.Text绑定默认情况下在losf焦点上更新)

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);
    }
}

和用法

<TextBox Text="{Binding SearchTerm, UpdateSourceTrigger=Explicit}" 
         my:TextBoxBehaviour.CommandOnEnterPressed="{Binding SearchCommand}"/>