Как захватить нажатие кнопки в ListView - PullRequest
1 голос
/ 10 января 2012

Я отображаю список элементов в WPF ListView, элементы имеют количество, код заказа и описание. Столбцы привязываются к полям в ObservableCollection, хранящемся в модели представления. Это все очень стандартно и работает как и ожидалось. Однако в столбце «Количество» в ListView я добавляю две кнопки «+» и «-», идея состоит в том, что при нажатии значение величины либо увеличивается, либо уменьшается. Проблема состоит в том, что, поскольку эти кнопки не привязаны к полю в ObservableCollection, я не могу получить ссылку от кнопки, нажатой в представлении списка, на запись в ObservableCollection. Я попытался выбрать элемент, выбранный в ListView, но это кнопка, которая выбирается при нажатии, а не элемент ListView. Я также зафиксировал элемент под указателем мыши, когда кнопка нажата, но ее можно нажать с помощью клавиатуры.

Я чувствую, что должен быть (простой!) Способ сделать это, но я не могу его найти.

Это XAML:

<ListViewName="AccessoriesContent" >
    <ListView.View>
        <GridView>
            <GridView.Columns>
                <GridViewColumn Header="Select">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel  Orientation="Horizontal" Name="QuantityStack">
                                <Button Name="SubtractAccessoryButton" Command="vx:DataCommands.SubtractAccessory" Content="-" />
                                <TextBox Name="QuantityTextBox" Text="{Binding Quantity, Mode=TwoWay}" />
                                <Button Name="AddAccessoryButton" Command="vx:DataCommands.AddAccessory" Content="+" />
                            </StackPanel>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Order Code"  DisplayMemberBinding="{Binding OrderCode}" />
                <GridViewColumn Header="Description"  DisplayMemberBinding="{Binding Description}" />
            </GridView.Columns>
        </GridView>
    </ListView.View>
</ListView>

Код позади:

    public MainWindow()
    {
        //CommandBindings.Add(
        InitializeComponent();
        AccessoryVM = new AccessoryViewModel();
        AccessoriesContent.ItemsSource = AccessoryVM.AccessoryCollection;
    }

И ViewModel:

class AccessoryViewModel
{
    ObservableCollection<AccessoryData> _AccessoryCollection =
    new ObservableCollection<AccessoryData>();

    public ObservableCollection<AccessoryData> AccessoryCollection
    { get { return _AccessoryCollection; } }

    public void PopulateAccessories(string order_code)
    {
        // Read the data and populate AccessoryCollection
    }
}

public class AccessoryData : INotifyPropertyChanged
{
    private int _quantity;
    public int Quantity
    {
        get { return _quantity; }
        set
        {
            this._quantity = value;
            Notify("Quantity");
        }
    }
    public string OrderCode { get; set; }
    public string Description { get; set; }


    public event PropertyChangedEventHandler PropertyChanged;
    protected void Notify(string propName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

Помимо этого у меня есть два метода SubtractAccessory и AddAccessory, которые запускаются кнопками, но мне еще предстоит заполнить их всем, что будет работать.

Ответы [ 3 ]

1 голос
/ 10 января 2012

Похоже, вы не опубликовали используемые вами команды.

В любом случае, если вы используете команды, вы можете использовать либо команды экземпляра, которые существуют в модели представления (тогда вам нужно будет связать команду ссвойство команды в DataContext) и, следовательно, имеет доступ к Quantity, или вы можете передать модель представления как CommandParameter, просто установив ее на {Binding}, затем в команде вы можете привести параметр к ВМ иизмените Quantity.

(Если бы вы использовали событие Click, вы могли бы просто привести sender к Button и привести его DataContext к ВМ)

1 голос
/ 10 января 2012

Другой вариант - создать RelayCommand (см. здесь ).В этой модели вы создаете свойство ICommand для каждого из ваших элементов.Затем вы устанавливаете это свойство для новой команды RelayCommand, которая принимает делегата, которого вы хотели бы запустить при активации этой команды.Так что это может быть метод QuantityUp и метод QuantityDown в ваших AccessoryData.Как только у вас есть свойство ICommand, вы просто привязываетесь к нему следующим образом, где QuantityUpCommand является вашим свойством ICommand.

 <GridViewColumn Header="" >
   <GridViewColumn.CellTemplate>
     <DataTemplate>
       <Button Height="15" Width="15" Content="+" Command="{Binding QuantityUpCommand}"/>
     </DataTemplate>
   </GridViewColumn.CellTemplate>
 </GridViewColumn>

AccessoryData будет выглядеть примерно так

private RelayCommand _quantityUpCommand;
public ICommand QuantityUpCommand
{
    get
    {
        if (_quantityUpCommand == null)
        {
            _quantityUpCommand = new RelayCommand(QuantityUp);
        }
        return _quantityUpCommand;
    }
}

public void QuantityUp(object obj)
{
   Quantity++;
}

И RelayCommand выглядит примерно так:

public class RelayCommand: ICommand
{
        #region Fields

        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;

        #endregion // Fields

        #region Constructors

        public RelayCommand(Action<object> execute)
            : this(execute, null)
        {
        }

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }
        #endregion // Constructors

        #region ICommand Members

        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }

        #endregion // ICommand Members
}
0 голосов
/ 10 января 2012

Вы можете пропустить текущий элемент через CommandParameter на кнопке, которая однозначно идентифицирует текущий элемент. Так что при выполнении Команды вы знаете, о каком предмете говорите. Если вы не можете найти уникальный токен в вашем предмете, вы можете даже передать весь предмет!

<Button Name="AddAccessoryButton" Command="vx:DataCommands.AddAccessory" CommandParameter="{Binding}" Content="+" />

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...