如何捕获ListView中的按钮按下

时间:2012-01-10 13:08:46

标签: wpf listview button

我在WPF ListView中显示项目列表,这些项目包含数量,订单代码和描述。这些列绑定到View Model中保存的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 个答案:

答案 0 :(得分:1)

您似乎没有发布您使用的命令。

无论如何,如果您使用命令,您可以使用视图模型上存在的实例命令(然后您需要将命令绑定到DataContext上的命令属性),因此可以访问{ {1}}或者您可以将视图模型作为Quantity传递,只需将其设置为CommandParameter,然后在命令中您可以将参数转换为VM并更改{Binding}

(如果您要使用Quantity事件,则可以将Click转换为sender并将其Button强制转换为VM

答案 1 :(得分:1)

另一种选择是创建一个RelayCommand(参见here)。在此模型中,您将在每个项目上创建ICommand属性。然后,将此属性设置为新的RelayCommand,该RelayCommand接受在激活该命令时要运行的委托。所以这可能是AccessoryData上的QuantityUp方法和QuantityDown方法。一旦你有了你的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
}

答案 2 :(得分:0)

您可以通过唯一标识当前项目的按钮上的CommandParameter传递当前项目。因此,在执行命令时,您知道您正在谈论的是什么项目。如果您在项目中找不到唯一的标记,您甚至可以传递整个项目!

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