如何将命令行为附加到ListView中的TextBox?

时间:2012-10-15 18:53:58

标签: wpf mvvm prism prism-4

我正在处理股票交易者参考实施的示例代码。

http://prism4.googlecode.com/svn/trunk/Prism4/

PositionSummaryView.xaml中有一个股票列表。在股票列表中,我添加了一个带有文本框的GridViewColumn,该文本框显示了股票的名称。当用户使用ReturnCommandBehavior行为点击enterkey时,我尝试在ViewModel中调用一个命令。

当我在文本框中按Enter键时,命中不会被命中。当我在列表之外有相同的文本框时,命中命令。

这适用于ListView

之外
<TextBox Grid.Column="0"  Text="test"    Infrastructure:ReturnKey.Command="{Binding Path=UpdateTickerSymbolCommand}"  ></TextBox>

这是我在TextBox中尝试过的绑定,但都没有效果:

 <TextBox Grid.Column="0"  Text="{Binding  Path=TickerSymbol}"  
                                  Infrastructure:ReturnKey.Command="{Binding Path=UpdateTickerSymbolCommand, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}"  ></TextBox>

第二次尝试

  <TextBox Grid.Column="0"  Text="{Binding  Path=TickerSymbol}"   Infrastructure:ReturnKey.Command="{Binding ElementName=root,Path= UpdateTickerSymbolCommand}" ></TextBox>

这是viewmodel:

using System.ComponentModel.Composition;
using System.Windows.Input;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.ViewModel;
using StockTraderRI.Infrastructure;
using StockTraderRI.Modules.Position.Controllers;
using Microsoft.Practices.Prism.Commands;

namespace StockTraderRI.Modules.Position.PositionSummary
{
    [Export(typeof(IPositionSummaryViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class PositionSummaryViewModel : NotificationObject, IPositionSummaryViewModel
    {
        private PositionSummaryItem currentPositionSummaryItem;

        private readonly IEventAggregator eventAggregator;

        public IObservablePosition Position { get; private set; }


        private ICommand updateTickerSymbolCommand;

        public ICommand UpdateTickerSymbolCommand { get { return this.updateTickerSymbolCommand; } }

        [ImportingConstructor]
        public PositionSummaryViewModel(IOrdersController ordersController, IEventAggregator eventAggregator, IObservablePosition observablePosition)
        {
            this.eventAggregator = eventAggregator;
            this.Position = observablePosition;

            BuyCommand = ordersController.BuyCommand;
            SellCommand = ordersController.SellCommand;
            updateTickerSymbolCommand = new DelegateCommand<string>(this.UpdateTickerSymbol); ;

            this.CurrentPositionSummaryItem = new PositionSummaryItem("FAKEINDEX", 0, 0, 0);
        }

        private void UpdateTickerSymbol(string tickerSymbol)
        {

        }



        public ICommand BuyCommand { get; private set; }

        public ICommand SellCommand { get; private set; }

        public string HeaderInfo
        {
            get { return "POSITION"; }
        }

        public PositionSummaryItem CurrentPositionSummaryItem
        {
            get { return currentPositionSummaryItem; }
            set
            {
                if (currentPositionSummaryItem != value)
                {
                    currentPositionSummaryItem = value;
                    this.RaisePropertyChanged(() => this.CurrentPositionSummaryItem);
                    if (currentPositionSummaryItem != null)
                    {
                        eventAggregator.GetEvent<TickerSymbolSelectedEvent>().Publish(
                            CurrentPositionSummaryItem.TickerSymbol);
                    }
                }
            }
        }
    }
}

按Enter键时我需要点击UpdateTickerSymbol?

修改

我现在看到我误解了

Binding ElementName=root

在一些示例代码中。我认为root是一个关键字,但它是必须在视图中给父控件的关键

这就是我使用

的原因
  <StackPanel x:Name="LayoutRoot" >

现在在父控件中

<TextBox Grid.Column="0"  Text="{Binding  Path=TickerSymbol}"   Infrastructure:ReturnKey.Command="{Binding ElementName=LayoutRoot, Path=UpdateTickerSymbolCommand}" ></TextBox>

表示TextBox,但命令仍未命中。

我还尝试了上面的语法,并在示例中使用了一个Button,并且它可以工作

<Button Grid.Column="0" Command="{Binding Path=DataContext.BuyCommand, ElementName=LayoutRoot}" CommandParameter="{Binding Path=TickerSymbol}" AutomationProperties.AutomationId="ActionsBuyButton" Template="{StaticResource AddButtonTemplate}"  Cursor="Hand" Width="30" />

2 个答案:

答案 0 :(得分:1)

你可以简单地使用TextBox.InputBindings,你想在文本上使用Mode = TwoWay和UpdateSourceTrigger = PropertyChanged。

<强>的.xaml

    <ListView HorizontalAlignment="Stretch" 
              Height="Auto" 
              ItemsSource="{Binding Collection}"
              VerticalAlignment="Stretch" 
              Width="Auto">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextBox Width="100" 
                         Text="{Binding MyText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                    <TextBox.InputBindings>
                        <KeyBinding Key="Enter" Command="{Binding MyCommand}" />
                    </TextBox.InputBindings>
                </TextBox>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

您的数据模型将是

<强>的.cs

public class DataModel : INotifyPropertyChanged
{
    private string m_myText;
    public string MyText
    {
        get { return m_myText; }
        set 
        { 
            m_myText = value;
            OnPropertyChanged("MyText");
        }
    }

    public ICommand MyCommand { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

视图模型上的集合

<强> ViewModel.cs

Collection = new ObservableCollection<DataModel> { new DataModel() { MyText = String.Empty, MyCommand = m_myCommand } };

答案 1 :(得分:1)

我下载了源代码。 TextBox似乎已经消失了。将TextBox的命令更改为DataContext.BuyCommand“修复”“问题”。命令“UpdateTickerSymbolCommand”似乎也不再可用,所以我也无法测试它。当前源也没有对StackPanel(LayoutRoot)的引用,所以这也是我无法跟踪的。我认为这里的关键问题是Command没有正确设置。