2013-08-16 73 views
1

我有一個WPF MVVM應用程序,其中有一個TreeView所有靜態項目保留在XAML頁面中。我如何知道在我的視圖模型中點擊了哪個MenuItem,以便我可以相應地顯示相應的頁面。如何知道使用mvvm點擊哪個treeview項目

<TreeView Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="MyTreeViewMenu" 
         VerticalAlignment="Stretch" Width="Auto" Opacity="1" 
        BorderThickness="1" BorderBrush="Black" Grid.Row="2"> 

     <TreeViewItem Header="Country" Width="Auto" HorizontalAlignment="Stretch" 
         ></TreeViewItem> 

     <TreeViewItem Header="View Details" Width="Auto" HorizontalAlignment="Stretch" IsEnabled="False"> 
       <TreeViewItem Header="User" /> 
       <TreeViewItem Header="Group" /> 
       <TreeViewItem Header="User Group" /> 
      </TreeViewItem> 
    </TreeView> 

回答

2

我想這Selected事件會在你的情況下,click同樣的效果。爲了確定哪一個TreeViewItem選擇你要添加事件Trigger

<TreeView Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="MyTreeViewMenu" 
         VerticalAlignment="Stretch" Width="Auto" Opacity="1" 
        BorderThickness="1" BorderBrush="Black" Grid.Row="2"> 

     <TreeViewItem Header="Country" Width="Auto" HorizontalAlignment="Stretch"></TreeViewItem>  
     <TreeViewItem Header="View Details" Width="Auto" HorizontalAlignment="Stretch" IsEnabled="False"> 
       <TreeViewItem Header="User" /> 
       <TreeViewItem Header="Group" /> 
       <TreeViewItem Header="User Group" /> 
      </TreeViewItem> 
       <i:Interaction.Triggers> 
        <i:EventTrigger EventName="SelectedItemChanged"> 
         <i:InvokeCommandAction 
         Command="{Binding selectItemCommand}" 
         CommandParameter="{Binding SelectedItem, ElementName=MyTreeViewMenu}"/> 
        </i:EventTrigger> 
       </i:Interaction.Triggers> 
</TreeView> 

您也可以使用,並確定哪些項目被傳遞給Command參數選擇的結果。

ViewModel應該是這個樣子:

private ICommand _selectItemCommand; 
public ICommand selectItemCommand 
{ 
    get 
    { 
     return _selectItemCommand ?? (_selectItemCommand = new RelayCommand(param => this.LoadPage(param))); 
    } 
} 

private void LoadPage(object selectedMenuItem) 
{ 
     ... 
} 
+0

'TreeViewItem.Selected'是事件不是嗎?你如何使用'StaticResource'來匹配'Command'和一個事件?此外,該請求是針對MVVM解決方案的。 – Sheridan

+0

@Sheridan是的..答覆已更新。 –

+0

在我的視圖模型中添加了命令和屬性。雖然命令正在菜單項選擇上被調用,但如何獲取selectedmenuItem?見下面的評論。 – user2519971

2

看一看在MSDN的TreeView.SelectedItem Property頁面。

您可以直接綁定到TreeView.SelectedItem屬性:

<TreeView ItemsSource="{Binding Items}" SelectedItem="{Binding Item, Mode=OneWay}" /> 

注意,TreeView.SelectedItem屬性只只讀,所以你必須使用一個OneWay結合......這意味着你不能設置選擇來自您的視圖模型的項目。爲此,您需要使用Attached Property創建自己的雙向選擇項目屬性。

編輯>>>

我道歉@ Scroog1,我通常使用一個AttachedProperty做到這一點。即使使用OneWay綁定,也是如此,使用此方法時出現錯誤。不幸的是,我的AttachedProperty代碼很長,但有另一種方法可以做到這一點。

我不一定會推薦這個,因爲它是從來沒有真正把UI屬性到您的數據對象是個好主意,但如果你添加一個IsSelected屬性的數據對象,那麼你可以直接將其綁定到TreeViewItem.IsSelected屬性:

<TreeView ItemsSource="Items" HorizontalAlignment="Stretch" ... Name="MyTreeViewMenu"> 
    <TreeView.ItemContainerStyle> 
     <Style TargetType="{x:Type TreeViewItem}"> 
      <Setter Property="IsSelected" Value="{Binding IsSelected}" /> 
     </Style> 
    </TreeView.ItemContainerStyle> 
</TreeView> 

我只是搜查,在這裏StackOverflow上的WPF MVVM TreeView SelectedItem後發現了一個「更全面」爲你解答。

或者,還有另外一種方法...您也可以使用TreeView.SelectedValueTreeView.SelectedValuePath屬性。基本思想是將TreeView.SelectedValuePath屬性設置爲數據對象上屬性的名稱。當選擇一個項目時,TreeView.SelectedValue屬性將被設置爲所選數據項目的屬性值。您可以從MSDN的How to: Use SelectedValue, SelectedValuePath, and SelectedItem頁面瞭解有關此方法的更多信息。如果你有一個唯一可識別的屬性,比如某種類型的標識符,這通常效果最好。此代碼示例從MSDN:

<TreeView ItemsSource="{Binding Source={StaticResource myEmployeeData}, 
XPath=EmployeeInfo}" Name="myTreeView" SelectedValuePath="EmployeeNumber" /> 

<TextBlock Margin="10">SelectedValuePath: </TextBlock> 
<TextBlock Margin="10,0,0,0" Text="{Binding ElementName=myTreeView, 
Path=SelectedValuePath}" Foreground="Blue"/> 

<TextBlock Margin="10">SelectedValue: </TextBlock> 
<TextBlock Margin="10,0,0,0" Text="{Binding ElementName=myTreeView, 
Path=SelectedValue}" Foreground="Blue"/> 
+0

我得到錯誤「SelectedItem」屬性是隻讀的,不能從標記設置。 – Scroog1

+0

請正確閱讀我的答案以解決您的問題...請注意關於'您*必須*使用OneWay綁定'的內容。 – Sheridan

+0

我正在使用OneWay綁定。 – Scroog1

0

除了綁定到TreeView.SelectedItem屬性:

當使用MVVM它讓我停止思考的UI事件,並開始在思考狀態UI。

您可以將ViewModel綁定到View的屬性。所以通常我會嘗試將SelectedItem綁定到ViewModel上的屬性,以便ViewModel知道選擇了什麼。

以同樣的方式,您可以添加一個屬性到顯示的ViewModel項目中,名爲Selected並將此屬性綁定到View中的複選框。這樣,您可以在ViewModel中輕鬆地啓用多項選擇並訪問所選項目。

0

爲了完整起見,這裏的附加屬性和TreeView子選項:

附加屬性選項

public static class TreeViewSelectedItemHelper 
{ 
    public static readonly DependencyProperty BindableSelectedItemProperty 
     = DependencyProperty.RegisterAttached(
      "BindableSelectedItem", 
      typeof (object), 
      typeof (TreeViewSelectedItemHelper), 
      new FrameworkPropertyMetadata(false, 
              OnSelectedItemPropertyChanged) 
       { 
        BindsTwoWayByDefault = true 
       }); 

    public static object GetBindableSelectedItem(TreeView treeView) 
    { 
     return treeView.GetValue(BindableSelectedItemProperty); 
    } 

    public static void SetBindableSelectedItem(
     TreeView treeView, 
     object selectedItem) 
    { 
     treeView.SetValue(BindableSelectedItemProperty, selectedItem); 
    } 

    private static void OnSelectedItemPropertyChanged(
     DependencyObject sender, 
     DependencyPropertyChangedEventArgs args) 
    { 
     var treeView = sender as TreeView; 
     if (treeView == null) return; 
     SetBindableSelectedItem(treeView, args.NewValue); 
     treeView.SelectedItemChanged -= HandleSelectedItemChanged; 
     treeView.SelectedItemChanged += HandleSelectedItemChanged; 
     if (args.OldValue != args.NewValue) 
      SetSelected(treeView, args.NewValue); 
    } 

    private static void SetSelected(ItemsControl treeViewItem, 
            object itemToSelect) 
    { 
     foreach (var item in treeViewItem.Items) 
     { 
      var generator = treeViewItem.ItemContainerGenerator; 
      var child = (TreeViewItem) generator.ContainerFromItem(item); 
      if (child == null) continue; 
      child.IsSelected = (item == itemToSelect); 
      if (child.HasItems) SetSelected(child, itemToSelect); 
     } 
    } 

    private static void HandleSelectedItemChanged(
     object sender, 
     RoutedPropertyChangedEventArgs<object> args) 
    { 
     if (args.NewValue is TreeViewItem) return; 
     var treeView = sender as TreeView; 
     if (treeView == null) return; 
     var binding = BindingOperations.GetBindingExpression(treeView, 
      BindableSelectedItemProperty); 
     if (binding == null) return; 
     var propertyName = binding.ParentBinding.Path.Path; 
     var property = binding.DataItem.GetType().GetProperty(propertyName); 
     if (property != null) 
      property.SetValue(binding.DataItem, treeView.SelectedItem, null); 
    } 
} 

子類選項

public class BindableTreeView : TreeView 
{ 
    public BindableTreeView() 
    { 
     SelectedItemChanged += HandleSelectedItemChanged; 
    } 

    public static readonly DependencyProperty BindableSelectedItemProperty = 
     DependencyProperty.Register(
      "BindableSelectedItem", 
      typeof (object), 
      typeof (BindableTreeView), 
      new FrameworkPropertyMetadata(
       default(object), 
       OnBindableSelectedItemChanged) {BindsTwoWayByDefault = true}); 

    public object BindableSelectedItem 
    { 
     get { return GetValue(BindableSelectedItemProperty); } 
     set { SetValue(BindableSelectedItemProperty, value); } 
    } 

    private static void OnBindableSelectedItemChanged(
     DependencyObject d, 
     DependencyPropertyChangedEventArgs e) 
    { 
     var treeView = d as TreeView; 
     if (treeView != null) SetSelected(treeView, e.NewValue); 
    } 

    private static void SetSelected(ItemsControl treeViewItem, 
            object itemToSelect) 
    { 
     foreach (var item in treeViewItem.Items) 
     { 
      var generator = treeViewItem.ItemContainerGenerator; 
      var child = (TreeViewItem) generator.ContainerFromItem(item); 
      if (child == null) continue; 
      child.IsSelected = (item == itemToSelect); 
      if (child.HasItems) SetSelected(child, itemToSelect); 
     } 
    } 

    private void HandleSelectedItemChanged(
     object sender, 
     RoutedPropertyChangedEventArgs<object> e) 
    { 
     SetValue(BindableSelectedItemProperty, SelectedItem); 
    } 
} 
相關問題