2013-07-16 109 views
0

我想從我的TreeView中獲取選定的項目,但有一些問題。 我正在關注MVVM構架。我的ViewModel包含我的模型中的一個類的集合。所以我用這個集合綁定了TreeView的ItemSource。我想將我的TreeView的selectedItem綁定到綁定集合的一個項目。我怎麼做。這是SelectedItem和IsSelected屬性的代碼。TreeView中的SelectedItem

private static sourceData _selectedItem = null; 
    /// <summary> 
    /// Selected Item in the tree 
    /// </summary> 
    public static sourceData SelectedItem 
    { 
     get { return _selectedItem; } 
     set 
     { 
      if (_selectedItem != value) 
      { 
       _selectedItem = value; 
      } 
     } 
    } 

    private bool _isSelected; 
    /// <summary> 
    /// Get/Set for Selected node 
    /// </summary> 
    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set 
     { 
      if (_isSelected != value) 
      { 
       _isSelected = value; 

       if (_isSelected) 
       { 
        SelectedItem = this; 
        OnPropertyChanged("IsSelected"); 
       } 
      } 
     } 
    } 

    /// <summary> 
    /// Property changed event 
    /// </summary> 
    public event PropertyChangedEventHandler PropertyChanged; 
    /// <summary> 
    /// Property changed event handler 
    /// </summary> 
    /// <param name="propertyName"></param> 
    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     var handler = this.PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 

當調試這一點,詮釋SelectedItem = this;「這個」指針包含到我的TreeView的是綁定的集合。我需要一個SelectedDataSource,以便我可以將它分配給選定的Item。我怎樣才能讓我的TreeView返回集合中的selectedItem?

據透露,這是我的TreeView

<TreeView Margin="5,0,0,0" ItemsSource="{Binding SourceData}" Width="390"> 
        <TreeView.ItemContainerStyle> 
         <Style TargetType="{x:Type TreeViewItem}"> 
          <Setter Property="IsSelected" Value="{Binding DataContext.IsSelected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" /> 
          <Setter Property="ContextMenu"> 
           <Setter.Value> 
            <ContextMenu Name="contextMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" > 
             <MenuItem Name="menuItem" Header="Rename" Command="{Binding RenameCommand}" /> 
            </ContextMenu> 
           </Setter.Value> 
          </Setter> 
          <Style.Triggers> 
           <Trigger Property="IsSelected" Value="True"> 
           </Trigger> 
          </Style.Triggers> 
         </Style> 
        </TreeView.ItemContainerStyle> 

P.S XAML代碼:如果我寫在我的模型上面的代碼中,我得到的一切工作完全正常。但是我不能在Model中正確使用上面的代碼,它必須在VM中。

任何幫助將不勝感激。

感謝

+0

可能的重複http://stackoverflow.com/questions/1000040/selecteditem-in-a-wpf-treeview – Nitesh

+0

我一直在使用附加行爲綁定到我的虛擬機中的ICommand。它很乾淨,但你必須記住,電視SelectedItem是一個只讀屬性,所以虛擬機只能檢查它。 –

+0

我只想讀取selectedItem。我不需要設置它。那麼如何使用附加行爲綁定到虛擬機中的ICommmand? – WAQ

回答

0

而且對你的問題的評論文章,對WPF的TreeView給人以MVVM開發一些獨特的挑戰,並且在這些之中是檢測當前選定的項目。爲此,您可以使用附加的行爲。首先,寫一個靜態類包含的行爲......

public static class TvBehaviour 
    { 
     #region TvSelectedItemChangedBehaviour (Attached DependencyProperty) 
     public static readonly DependencyProperty TvSelectedItemChangedBehaviourProperty = 
      DependencyProperty.RegisterAttached("TvSelectedItemChangedBehaviour", 
               typeof (ICommand), 
               typeof (TvBehaviour), 
               new PropertyMetadata(
                OnTvSelectedItemChangedBehaviourChanged)); 

     public static void SetTvSelectedItemChangedBehaviour(DependencyObject o, ICommand value) 
     { 
      o.SetValue(TvSelectedItemChangedBehaviourProperty, value); 
     } 
     public static ICommand GetTvSelectedItemChangedBehaviour(DependencyObject o) 
     { 
      return (ICommand) o.GetValue(TvSelectedItemChangedBehaviourProperty); 
     } 
     private static void OnTvSelectedItemChangedBehaviourChanged(DependencyObject d, 
                    DependencyPropertyChangedEventArgs e) 
     { 
      TreeView tv = d as TreeView; 
      if (tv != null) 
      { 
       tv.SelectedItemChanged += (s, a) => 
        { 
         GetTvSelectedItemChangedBehaviour(tv).Execute(a.NewValue); 
         a.Handled = true; 
        }; 
      } 
     } 
     #endregion 

}

然後導入類的命名空間到你的XAML(可使用的xmlns)。然後,您可以沿着這些線聲明一個TreeView ...

<TreeView ItemsSource="{Binding MyList}" 
       ItemTemplate="{StaticResource My_data_template}" 
       tvBinding:TvBehaviour.TvSelectedItemChangedBehaviour="{Binding    
          SelectedItemCommand}" 
       SelectedValuePath="Name" 
       > 
    </TreeView> 

這會將電視行爲「連接」到虛擬機中的ICommand。最後,在虛擬機中聲明ICommand ...

public ICommand SelectedItemCommand {get;組; }

並對其進行初始化...

SelectedItemCommand = new RelayCommand(ExecuteSelectedItemCommand, 
             CanExecuteSelectedItemCommand); 

,然後實現您的代表...

private void ExecuteSelectedItemCommand(object obj) 
    { 
     // downcast 'obj' to get the instance of the selected item 
    } 
    private bool CanExecuteSelectedItemCommand(object obj) 
    { 
     return true; 
    } 

當用戶選擇一個電視項目,你的「執行」代表將獲得盒裝該項目的實例,你可以unbox它等等等等等

請注意,在這個例子中的附加行爲假設電視的生命週期是一樣的應用程序,否則你必須聯合國連接附加的行爲。它還假定TV ItemsSource對某些合理的東西有約束力。

這將解決在保持MVVM兼容(如果存在符合MVVM的情況下)的情況下獲取TV SelectedItem的問題。

我使用的Relay Command類是從MSDN中的鏈接文章中獲取的。爲了便於參考,這裏是...

public class RelayCommand : ICommand 
{ //http://msdn.microsoft.com/en-us/magazine/dd419663.aspx 
    public RelayCommand(Action<object> execute, Predicate<object> canExecute) 
    { 
     _execute = execute; 
     _canExecute = canExecute; 
    } 
    public bool CanExecute(object parameter) 
    { 
     return _canExecute(parameter); 
    } 
    public event EventHandler CanExecuteChanged 
    { 
     add { CommandManager.RequerySuggested += value; } 
     remove { CommandManager.RequerySuggested -= value; } 
    } 
    public void Execute(object parameter) 
    { 
     _execute(parameter); 
    } 
    private readonly Action<object> _execute; 
    private readonly Predicate<object> _canExecute; 
} 

使用上面的MSDN鏈接可以獲取關於此類的更多信息。

+0

我不能做SelectedItemCommand的初始化。它說RelayCommand有一些無效的參數。當我刪除ExecuteSelectedItemCommand的參數時,錯誤消失。但這不能幫助我 – WAQ

+0

可能是一個不同的版本。回答編輯。我已將原始版本添加到我的答案中。在這個版本中,代表是強類型的(這是你需要的)。改爲... –

相關問題