2012-01-10 64 views
1

我正在顯示WPF ListView中的項目列表,項目有一個數量,訂單代碼和一個描述。列被綁定到View Model中保存的ObservableCollection中的字段。這一切都非常標準,並按預期工作。但是,在ListView的Quantity Column中,我添加了兩個按鈕+和 - ,這個想法是,當它們被按下時,數量的值或者遞增或者遞減。問題是,因爲這些按鈕沒有綁定到ObservableCollection中的字段,我無法從列表視圖中的按鈕鏈接到ObservableCollection中的記錄。我已經試過在ListView中選擇的項目,但它是按下時被選中的按鈕而不是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; 
    } 

和視圖模型:

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被觸發由按鈕,但我還沒有填充他們的任何工作。

回答

1

另一種選擇是創建一個RelayCommand(見here)。在這個模型中,你爲每個項目創建一個ICommand屬性。然後,將該屬性設置爲一個新的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 
} 
+0

謝謝馬克,這正是我正在尋找的東西 - 作品一種享受。 – Marcus 2012-01-10 15:12:54

+0

很高興我能幫到你。在我遇到這種解決方案之前,我在我的同一堵牆上撞了一會兒。如果這對您有用,如果您將此標記爲您接受的解決方案,我將不勝感激。 – 2012-01-10 15:19:56

0

您可以通過當前項目通過按鈕上的CommandParameter唯一標識當前項目。所以在執行命令時你知道你在說什麼。如果你在你的物品中找不到一個唯一的標記,你甚至可以通過整個物品!

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

1

你似乎並沒有公佈你使用的命令。無論如何,如果您確實使用了命令,您可以使用視圖模型中存在的實例命令(然後您需要將該命令綁定到DataContext上的命令屬性),因此可以訪問Quantity,或者您也可以訪問QuantityQuantity將視圖模型設置爲CommandParameter,只需將其設置爲{Binding},然後在該命令中,您可以將該參數投射到虛擬機並更改Quantity

(如果你使用Click事件,你可以只投了senderButton並投它DataContext到VM)

+0

+1指出你可以從'Button.DataContext'獲得視圖模型 – Rachel 2012-01-10 14:47:39

+0

HB感謝你的回答。我正在使用一個實例命令,但遇到了CommandParameter的問題,我會再看一次。 – Marcus 2012-01-10 15:16:44

+0

對於剛接觸MVVM框架的程序員,我想在這裏指出DataContext並不總是包含ViewModel。程序員必須明確地將DataContext設置爲等於代碼中的ViewModel,以便以後能夠從DataContext獲取ViewModel。 – 2012-01-10 15:17:13