【问题标题】:Why does a command bound to a textbox not fire in wpf?为什么绑定到文本框的命令不会在 wpf 中触发?
【发布时间】:2015-12-19 04:18:30
【问题描述】:

我已使用触发器将文本框绑定到命令,但当用户按键盘上的 Enter 时似乎没有任何反应。为什么会这样?我想要发生的是当用户点击输入时,它会将名称附加到列表并清除输入字段。

主要关注领域如下: xml sn-p

   <TextBox Grid.Row="0" Text="{Binding InputText, UpdateSourceTrigger=PropertyChanged}">
            <TextBox.InputBindings>
                <KeyBinding Key="Enter" Command="{Binding Path=CmdSomething, UpdateSourceTrigger=PropertyChanged}"/>
            </TextBox.InputBindings>
        </TextBox>

及其在主视图模型中调用此命令:

 public void CmdSomething()
        {
            Console.WriteLine(InputText);
        }

下面是整个项目的代码,以防有人需要它来测试。

项目代码

VNodes.cs

namespace WpfApplication1
{
    public class VNode
    {
        public string Name { get; set; }
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:local="clr-namespace:WpfApplication1">

    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <TextBox Grid.Row="0" Text="{Binding InputText, UpdateSourceTrigger=PropertyChanged}">
            <TextBox.InputBindings>
                <KeyBinding Key="Enter" Command="{Binding Path=CmdSomething, UpdateSourceTrigger=PropertyChanged}"/>
            </TextBox.InputBindings>
        </TextBox>

        <ListBox Grid.Row="1" Background="LightBlue" ItemsSource="{Binding VNodes}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <WrapPanel>
                        <TextBlock Text="{Binding Name}" FontWeight="Bold" />
                    </WrapPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

MainViewModel

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
using System.Collections.ObjectModel;


namespace WpfApplication1
{
    public class MainViewModel : ObservableObject
    {
        private ObservableCollection<VNode> _vnodes;
        public ObservableCollection<VNode> VNodes
        {
            get { return _vnodes; }
            set
            {
                _vnodes = value;
                NotifyPropertyChanged("VNodes");
            }
        }

        private string _inputText = "";
        public string InputText
        {
            get { return _inputText; }
            set
            {
                if (value != _inputText)
                {
                    _inputText = value;
                }
            }
        }

        public void CmdSomething()
        {
            Console.WriteLine(InputText);
        }

        public MainViewModel()
        {
            //hard coded data for testing
            VNodes = new ObservableCollection<VNode>();
            List<string> names = new List<string>() { "Tammy", "Doug", "Mike", "Joey", "Leslie", "Emily", "Tom" };

            foreach(string name in names)
            {
                VNode item = new VNode();
                item.Name = name;
                VNodes.Add(item);
            }
        }
    }
}

ObservableObjects.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace WpfApplication1
{
    public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    代码中的 CmdSomething 不是 ICommand,而只是一个函数。

    现在有两种方法可以使其适用于您的情况。

    创建一个 ICommand。精彩tutorial

    如果 MyCommand 是 ViewModel 中 ICommand 类型的属性,则绑定自定义命令:

    <TextBox.InputBindings>
          <KeyBinding Key="Enter" Command="{Binding MyCommand, Mode=OneWay}" />
    </TextBox.InputBindings>
    

    如果你想调用你的函数,那么你可以使用CallMethodAction 行为。 Discussion。更多教程可以搜索谷歌。

    对于您当前的问题,这没有任何问题:

    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

           <TextBox x:Name="textBox" Margin="144,80,288,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Height="32">
                <i:Interaction.Triggers>
                    <ei:KeyTrigger Key="Return"> <!-- Note Blend Behaviors don't use Enter, instead use Return value -->
                        <ei:CallMethodAction TargetObject="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}" MethodName="CmdSomething"/>
                    </ei:KeyTrigger>
                </i:Interaction.Triggers>
            </TextBox>
    

    Good discussion

    【讨论】:

    • @JokerMartini 你设置了 CommandTarget="{Binding ElementName=MyTextBox}"
    • 由于某种原因似乎仍然没有做任何事情。
    • @JokerMartini 当你说它不工作时,告诉错误/异常/屏幕截图。您可以使用 screentogif 转换器实用程序。
    • 将建议的解决方案放入我的代码时没有任何反应。该函数永远不会被执行
    • @JokerMartini 我将制作一个示例应用程序,并将在 2 小时后上传到 Dropbox。
    猜你喜欢
    • 2017-04-18
    • 2017-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多