【问题标题】:Textbox binding with trigger带触发器的文本框绑定
【发布时间】:2015-03-11 08:19:46
【问题描述】:

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

我的 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="TextChanged" 在这里起作用。但不确定其他的东西。

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

【问题讨论】:

    标签: c# wpf data-binding textbox datatemplate


    【解决方案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}"/>
    

    【讨论】:

    • 来自链接重复问题的 KeyBinding 解决方案是我的首选方式。它真的很简单,只需极少的工作即可掌握。如果您要管理大量相同的控件,那么能够在样式中设置上述答案会很棒。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-25
    • 2012-09-18
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 2014-10-07
    相关资源
    最近更新 更多