2011-05-25 117 views
0

是否可以將命令綁定到ListView的ItemSelectionChanged?怎麼樣?如果不可能,當列表視圖的選擇更改時,還有另一種方法可以調用命令嗎?如何將命令綁定到ListView的ItemSelectionChanged事件?

+1

不能綁定SelectedItems一個屬性? – 2011-05-25 03:04:53

+0

@Derek:這也是一個答案,我認爲 – 2011-05-25 06:06:11

+0

我得到這個:Error 'SelectedItems'屬性是隻讀的,不能從標記中設置。 – 2011-05-25 06:22:18

回答

1

是 - MVVM-light框架支持將數據綁定到路由事件的命令。見http://blog.galasoft.ch/archive/2009/11/05/mvvm-light-toolkit-v3-alpha-2-eventtocommand-behavior.aspx

<Rectangle Fill="White" 
      Stroke="Black" 
      Width="200" 
      Height="100"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="MouseEnter"> 
      <cmd:EventToCommand Command="{Binding TestCommand, 
              Mode=OneWay}" 
       CommandParameter="{Binding Text, 
            ElementName=MyTextBox, 
            Mode=OneWay}" 
       MustToggleIsEnabledValue="True" /> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</Rectangle> 
0

起初,我在我的項目中使用,其中selectedItems一個傳遞作爲參數的命令。這種方法的缺點是用戶不得不點擊命令按鈕來啓動操作,但這在大多數情況下滿足了我的要求。

實現你想要的東西就像是erash發佈 - 使用一種像mvvm-light一樣的EventToCommand行爲。

另一種方法是創建一個附加的行爲來綁定到viewmodel中的selecteditems。你必須善於下面的代碼的ListView或創造一些更普遍的:)

<DataGrid AttachedProperties:DatagridService.SelectedItemsSource="{Binding SelectedItems, Mode=OneWay}" /> 

視圖模型:

public ObservableCollection<object> SelectedItems//init collection just ONCE! 
    { 
     get 
     { 
      if (this.selectedItems == null) 
      { 
       this.selectedItems = new ObservableCollection<object>(); 
       this.selectedItems.CollectionChanged += 
        new System.Collections.Specialized.NotifyCollectionChangedEventHandler(SelectedItemsCollectionChanged); 
      } 
      return this.selectedItems; 
     } 

    } 

    private void SelectedItemsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     //this is called when ever the selecteditems changed 
    } 

附加的行爲:

public static class DatagridService 
{ 
    #region SelectedItemSource 

    #region Attached Property Declaration 

    /// <summary> 
    /// Identifies the ListBoxExtension.SelectedItemsSource attached property. 
    /// </summary> 
    public static readonly DependencyProperty SelectedItemsSourceProperty = 
     DependencyProperty.RegisterAttached(
      "SelectedItemsSource", 
      typeof(IList), 
      typeof(DatagridService), 
      new PropertyMetadata(
       null, 
       new PropertyChangedCallback(OnSelectedItemsSourceChanged))); 

    #endregion 

    #region Attached Property Accessors 

    /// <summary> 
    /// Gets the IList that contains the values that should be selected. 
    /// </summary> 
    /// <param name="element">The ListBox to check.</param> 
    public static IList GetSelectedItemsSource(DependencyObject element) 
    { 
     if (element == null) 
      throw new ArgumentNullException("element"); 

     return (IList)element.GetValue(SelectedItemsSourceProperty); 
    } 

    /// <summary> 
    /// Sets the IList that contains the values that should be selected. 
    /// </summary> 
    /// <param name="element">The ListBox being set.</param> 
    /// <param name="value">The value of the property.</param> 
    public static void SetSelectedItemsSource(DependencyObject element, IList value) 
    { 
     if (element == null) 
      throw new ArgumentNullException("element"); 

     element.SetValue(SelectedItemsSourceProperty, value); 
    } 

    #endregion 

    #region IsResynchingProperty 

    // Used to set a flag on the ListBox to avoid reentry of SelectionChanged due to 
    // a full syncronisation pass 
    private static readonly DependencyPropertyKey IsResynchingPropertyKey = 
     DependencyProperty.RegisterAttachedReadOnly(
      "IsResynching", 
      typeof(bool), 
      typeof(DatagridService), 
      new PropertyMetadata(false)); 

    #endregion 

    #region Private Static Methods 

    private static void OnSelectedItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     DataGrid grd = d as DataGrid; 
     if (grd == null) 
      throw new InvalidOperationException("The DataGridExtension.SelectedItemsSource attached " + 
       "property can only be applied to DataGrid controls."); 

     grd.SelectionChanged -= new SelectionChangedEventHandler(OnDataGridSelectionChanged); 

     if (e.NewValue != null) 
     { 
      ListenForChanges(grd); 
     } 

     BindingExpression bexp = grd.GetBindingExpression(SelectedItemsSourceProperty); 
     if (bexp != null) 
      bexp.UpdateSource(); 

    } 

    private static void ListenForChanges(DataGrid grd) 
    { 
     // Wait until the element is initialised 
     if (!grd.IsInitialized) 
     { 
      EventHandler callback = null; 
      callback = delegate 
      { 
       grd.Initialized -= callback; 
       ListenForChanges(grd); 
      }; 
      grd.Initialized += callback; 
      return; 
     } 

     grd.SelectionChanged += new SelectionChangedEventHandler(OnDataGridSelectionChanged); 
     ResynchList(grd); 
    } 

    private static void OnDataGridSelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     DataGrid grd = sender as DataGrid; 
     if (grd != null) 
     { 
      bool isResynching = (bool)grd.GetValue(IsResynchingPropertyKey.DependencyProperty); 
      if (isResynching) 
       return; 

      IList list = GetSelectedItemsSource(grd); 

      if (list != null) 
      { 
       foreach (object obj in e.RemovedItems) 
       { 
        if (list.Contains(obj)) 
         list.Remove(obj); 
       } 
       foreach (object obj in e.AddedItems) 
       { 

        if (!list.Contains(obj)) 
         list.Add(obj); 
       } 
      } 
     } 
    } 

    private static void ResynchList(DataGrid grd) 
    { 
     if (grd != null) 
     { 
      grd.SetValue(IsResynchingPropertyKey, true); 
      IList list = GetSelectedItemsSource(grd); 

      if (grd.SelectionMode == DataGridSelectionMode.Single) 
      { 
       grd.SelectedItem = null; 
       if (list != null) 
       { 
        if (list.Count > 1) 
        { 
         // There is more than one item selected, but the listbox is in Single selection mode 
         throw new InvalidOperationException("DataGrid is in Single selection mode, but was given more than one selected value."); 
        } 

        if (list.Count == 1) 
         grd.SelectedItem = list[0]; 
       } 
      } 
      else 
      { 
       grd.SelectedItems.Clear(); 
       if (list != null) 
       { 
        foreach (object obj in grd.Items) 
         if (list.Contains(obj)) 
          grd.SelectedItems.Add(obj); 
       } 
      } 

      grd.SetValue(IsResynchingPropertyKey, false); 
     } 
    } 

    #endregion 

    #endregion 
} 
相關問題