如何连接TextBox的TextChanged事件和Command以便在Silverlight中使用MVVM模式

Ray*_*Ray 17 silverlight xaml mvvm

最近,我意识到MVVM模式对Silverlight应用程序非常有用,并研究如何将它应用到我的项目中.

顺便说一句,如何用Command连接文本框的textChanged事件?Button有Command属性,但Textbox没有commapd属性.如果Controls没有命令属性,如何组合ICommand和Control的事件?

我得到了以下xaml代码

<UserControl.Resources>
        <vm:CustomerViewModel x:Key="customerVM"/>    
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" 
          Background="White" 
          DataContext="{Binding Path=Customers, Source={StaticResource customerVM}, Mode=TwoWay}" >

        <StackPanel>
            <StackPanel Orientation="Horizontal"
                        Width="300"
                        HorizontalAlignment="Center">
                <TextBox x:Name="tbName" 
                         Width="50" 
                         Margin="10"/>
                <Button Width="30" 
                        Margin="10" 
                        Content="Find"
                        Command="{Binding Path=GetCustomersByNameCommand, Source={StaticResource customerVM}}"
                        CommandParameter="{Binding Path=Text, ElementName=tbName}"/>
            </StackPanel>
            <sdk:DataGrid ItemsSource="{Binding Path=DataContext, ElementName=LayoutRoot}"
                          AutoGenerateColumns="True"
                          Width="300"
                          Height="300"/>
        </StackPanel>
    </Grid>
Run Code Online (Sandbox Code Playgroud)

我想要做的是,如果用户在文本框中输入一些文本,数据将显示在数据网格中而不是使用按钮单击.我知道内置了自动完成框控件.但是,我想知道如何在没有Command属性的控件中调用ViewModel类中的Command属性,例如textbox.

谢谢

Ken*_*art 23

为什么不将Text属性绑定到视图模型上的属性?这样,您可以在更改时收到通知,并获得新值:

public string MyData
{
    get { return this.myData; }
    set
    {
        if (this.myData != value)
        {
            this.myData = value;
            this.OnPropertyChanged(() => this.MyData);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

XAML:

<TextBox Text="{Binding MyData}"/>
Run Code Online (Sandbox Code Playgroud)

  • @kwon,这个答案仍然有效.您只需在绑定中设置`UpdateSourceTrigger = PropertyChanged`,每次用户在TextBox中键入一个字符时,VM属性都会更新.所以你只需要在属性设置器中做任何你需要做的事情 (13认同)
  • @Thomas,UpdateSourcetrigger是WPF,在Silverlight中不起作用. (2认同)
  • UpdateSourceTrigger = PropertyChanged在SL5绑定中可用 (2认同)

Jer*_*ess 20

这是最简单的方法.如上所述,将文本框绑定到视图模型上的属性.然后,只需在文本框中添加一个代码隐藏(是的,我正在与MVVM进行代码隐藏,它不是世界末日)事件.添加TextChanged事件,然后只需刷新绑定.

总而言之,对于视图模型,您将拥有类似的内容:

public class MyViewModel 
{
    private string _myText;

    public string MyText 
    {
        get { return _myText; }
        set 
        {
            _myText = value;
            RaisePropertyChanged("MyText"); // this needs to be implemented
            // now do whatever grid refresh/etc
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的XAML中,你将拥有:

<TextBox Text="{Binding MyText,Mode=TwoWay}" TextChanged="TextBox_TextChanged"/>
Run Code Online (Sandbox Code Playgroud)

最后,在后面的代码中,只需执行以下操作:

public void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
   var binding = ((TextBox)sender).GetBindingExpression(TextBox.TextProperty);
   binding.UpdateSource();
}
Run Code Online (Sandbox Code Playgroud)

这将导致您的属性在文本更改时随时更新.}

  • 问题是......为什么?为什么要尝试减少代码隐藏.在代码中隐藏事件或者在XAML中指定附加行为之间的区别是什么?你仍然有code-behidn,在一种情况下它是显式的(行为),另一种是隐式的(代码隐藏文件).你可以用Trigger来解决这个问题,但我不确定你为什么要做额外的工作. (4认同)
  • 我尝试过这个并且效果很好。但是,我也尝试使用 UpdateSourceTrigger=PropertyChanged (如其他评论/答案中提到的),而不是后面的 TextChanged 代码,它有效!这是 Silverlight 5 中添加的功能,因此您现在可以摆脱代码隐藏:-) (2认同)

Dog*_*uca 9

这是MvvmLight的做法!归功于GalaSoft Laurent Bugnion.

<sdk:DataGrid Name="dataGrid1" Grid.Row="1"
    ItemsSource="{Binding Path=CollectionView}"
    IsEnabled="{Binding Path=CanLoad}"
    IsReadOnly="True">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <cmd:EventToCommand
                Command="{Binding SelectionChangedCommand}"
                CommandParameter="{Binding SelectedItems, ElementName=dataGrid1}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</sdk:DataGrid>
Run Code Online (Sandbox Code Playgroud)

资料来源: http ://blog.galasoft.ch/archive/2010/05/19/handling-datagrid.selecteditems-in-an-mvvm-friendly-manner.aspx

  • 请注意,在XAML中正确导入`i`命名空间是`xmlns:i ="http://schemas.microsoft.com/expression/2010/interactivity"` (3认同)

Viv*_*ara 7

只需使用

<TextBox Text="{Binding MyText,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
Run Code Online (Sandbox Code Playgroud)


小智 6

在定义部分,我们添加:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Run Code Online (Sandbox Code Playgroud)

如果您使用TextBox,请添加对我们要检测的事件的引用:

<TextBox Text="{Binding TextPrintersFilter}">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="TextChanged">          
      <i:InvokeCommandAction Command="{Binding FilterTextChangedCommand}"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</TextBox>
Run Code Online (Sandbox Code Playgroud)

在ViewModel中添加Commad的代码:

public ICommand FilterTextChangedCommand
{
  get
  {
    if (this._filterTextChangedCommand == null)
    {
      this._filterTextChangedCommand =
        new RelayCommand(param => this.OnRequestFilterTextChanged());
    }
    return this._filterTextChangedCommand;
  }
}

private void OnRequestFilterTextChanged()
{
  // Add code
}
Run Code Online (Sandbox Code Playgroud)

不要忘记执行绑定文本:

private string _textPrintersFilter;
public string TextPrintersFilter
{
  get { return _textPrintersFilter; }
  set
  {
    _textPrintersFilter = value;
    this.RaisePropertyChange(nameof(TextPrintersFilter));
  }
}
Run Code Online (Sandbox Code Playgroud)