Question

I am working with the sample code for the stock trader reference implementation.

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

There is a list of stocks in PositionSummaryView.xaml. In the list of stocks I added a GridViewColumn with a Textbox that displays the name of the stock. I try to call a command in the ViewModel when the user hits the enterkey by using the behaviour ReturnCommandBehavior.

The command is not hit when I press enter in the textbox. When I have the same textbox outside of the list, the command is hit.

This works outside of the ListView

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

This is the bindings I tried in the TextBox, but none works:

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

Second try

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

Here is the 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);
                    }
                }
            }
        }
    }
}

What do I need to hit UpdateTickerSymbol when pressing enter key?

EDIT

I now saw that I misinterpreted

Binding ElementName=root

in some sample code. I thought root is a keyword, but it is the key that has to be given to a parent control in the view

Thats why I used

  <StackPanel x:Name="LayoutRoot" >

in a parent controll now and

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

for the TextBox, but the command is still not hit.

I also tried the above syntax with a Button in the sample, and it worked

<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" />
Was it helpful?

Solution

I downloaded the source. The TextBox seemed to have disappeared. Changing the Command of the TextBox to DataContext.BuyCommand "fixed" the "problem". The command "UpdateTickerSymbolCommand" also seemed no longer available, so I wasn't able to test this as well. The current source also doesn't have a reference to the StackPanel (LayoutRoot), so this also I was unable to track. I think the key problem here was the Command not having been set properly.

OTHER TIPS

You can simply use TextBox.InputBindings and you want Mode=TwoWay and UpdateSourceTrigger=PropertyChanged on text.

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

Your data model for this would be

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

Collection on view model

ViewModel.cs

Collection = new ObservableCollection<DataModel> { new DataModel() { MyText = String.Empty, MyCommand = m_myCommand } };
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top