2013-07-08 40 views
0

我遇到以下代碼的問題。我有一個綁定到集合的TreeView控件。 TreeView會得到滿意的結果。 HOwever「IsSelected」屬性和ContextMenu的點擊命令不會觸發。以下是XAML代碼。無法啓動TreeView特有事件

<UserControl x:Class="Plan.Views.PadView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:v="clr-namespace:Planner.Views" 
      xmlns:vm="clr-namespace:Planner.ViewModels" 
    <Grid> 
     <StackPanel Orientation="Vertical"> 
      <Grid> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto" /> 
       </Grid.RowDefinitions> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="*" /> 
       </Grid.ColumnDefinitions> 
       <StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" OpacityMask="#FFECF5F5"> 
        <TreeView ItemsSource="{Binding Pads}" Name="tree_View" Width="190"> 
         <TreeView.ItemContainerStyle > 
          <Style TargetType="{x:Type TreeViewItem}"> 
           <Setter Property="IsSelected" Value="{Binding WellPadViewModel.IsSelected}" /> 
           <Setter Property="ContextMenu"> 
            <Setter.Value> 
             <ContextMenu> 
              <MenuItem Header="Rename" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Path=DataContext.RenameCommand}" /> 
             </ContextMenu> 
            </Setter.Value> 
           </Setter> 
           <Style.Triggers> 
            <Trigger Property="IsSelected" Value="True"> 
            </Trigger> 
           </Style.Triggers> 
          </Style> 
         </TreeView.ItemContainerStyle > 
         <TreeView.ItemTemplate> 
          <HierarchicalDataTemplate ItemsSource="{Binding Members}"> 
           <StackPanel Orientation="Horizontal"> 
            <TextBlock Text="{Binding Name}" > 
             <TextBlock.InputBindings> 
               <KeyBinding Key="F2" Command="{Binding RenameCommand}"/> 
              </TextBlock.InputBindings> 
            </TextBlock> 
           </StackPanel> 
         </HierarchicalDataTemplate> 
         </TreeView.ItemTemplate> 
        </TreeView> 
       </StackPanel> 
      </Grid> 
     </StackPanel> 
    </Grid> 
</UserControl> 

這裏是我的ViewModel

using System; 
using System.Collections.ObjectModel; 
using System.Windows; 
using System.Windows.Input; 
using System.ComponentModel; 
using WPFApplication; 

namespace FieldPlanner.ViewModels 
{ 
    public class PlanViewModel : BaseViewModel 
    { 
     Collection<Pads> pads = new Collection<Pads>(); 
     public PlanViewModel() 
     { 
      IsSelected = true; 
      pads = new Collection<Pad>(); 
     } 

     private ICommand _RenameCommand; 

     public ICommand RenameCommand 
     { 
      get 
      { 
       if (_RenameCommand == null) 
       { 
        _RenameCommand = new RelayCommand1((o) => 
        { 
         // Your logic should go here 
         MessageBox.Show("Please rename me"); 
        }); 
       } 
       return _RenameCommand; 
      } 
     } 

     public ObservableCollection<PadInfo> Members { get; set; } 

     private static object _selectedItem = null; 
     // This is public get-only here but you could implement a public setter which also selects the item. 
     // Also this should be moved to an instance property on a VM for the whole tree, otherwise there will be conflicts for more than one tree. 
     public static object SelectedItem 
     { 
      get { return _selectedItem; } 
      private set 
      { 
       if (_selectedItem != value) 
       { 
        _selectedItem = value; 
        OnSelectedItemChanged(); 
       } 
      } 
     } 

     public static void OnSelectedItemChanged() 
     { 
      // Raise event/do other things 
     } 

     private bool _isSelected; 
     public bool IsSelected 
     { 
      get { return _isSelected; } 
      set 
      { 
       if (_isSelected != value) 
       { 
        _isSelected = value; 
        OnPropertyChanged("IsSelected"); 
        if (_isSelected) 
        { 
         SelectedItem = this; 
        } 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      var handler = this.PropertyChanged; 
      if (handler != null) 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    /// <summary> 
    /// Class to hold the Pads info for a tree 
    /// </summary> 
    public class Pad 
    { 
     /// <summary> 
     /// Default Constructor 
     /// </summary> 
     public Pad() 
     { 
      this.Members = new ObservableCollection<PadInfo>(); 
     } 

     /// <summary> 
     /// Name of the pad 
     /// </summary> 
     public string Name { get; set; } 

     /// <summary> 
     /// Members of the pad 
     /// </summary> 
     public ObservableCollection<PadInfo> Members { get; set; } 
    } 

    /// <summary> 
    /// Class to hold the well and slot IDs snapped to a pad 
    /// </summary> 
    public class PadInfo 
    { 
     /// <summary> 
     /// Slot ID 
     /// </summary> 
     public string SlotID { get; set; } 

     /// <summary> 
     /// Well ID 
     /// </summary> 
     public string WellID { get; set; } 
    } 

    public class RelayCommand1 : ICommand 
    { 
     #region Fields 
     readonly Action<object> _execute; 
     readonly Predicate<object> _canExecute; 
     #endregion // Fields 

     #region Constructors 
     public RelayCommand1(Action<object> execute) 
      : this(execute, null) 
     { 
     } 
     public RelayCommand1(Action<object> execute, Predicate<object> canExecute) 
     { 
      if (execute == null) 
       throw new ArgumentNullException("execute"); 

      _execute = execute; 
      _canExecute = canExecute; 
     } 
     #endregion // Constructors 
     #region ICommand Members 
     // [DebuggerStepThrough] 
     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

你有兩個問題:

IsSelected:

<Setter Property="IsSelected" Value="{Binding WellPadViewModel.IsSelected}" /> 

在樹型視圖的DataContext設置爲墊和墊的實例沒有財產IsSelected你必須做某事像這個:

<Setter Property="IsSelected" Value="{Binding DataContext.IsSelected, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}" /> 

ContextMenu的問題更爲嚴重。 ContextMenu不在VisualTree中,因此您無法綁定到RelativeSource。解決方案是在這裏WPF Relative source- Cannot find source for binding with reference

問候

+0

太好了。非常感謝。這解決了我的一半問題。但我無法觸發ContextMenu觸發器。可能我沒有正確地獲取鏈接中的信息。你能否詳細說明一下。我相信我已經非常接近於通過觸發:) –

+0

這似乎已修復了選定的項目問題。該屬性確實被解僱,我可以使用它來設置選定的項目。 但重命名ContextMenu的屬性仍然沒有觸發。這是我試過的。我們可以通過下面的例子來說明如何使用DataItem對象:必須按照上述代碼進行設置。 –

+0

您無法使用RelativeSource進行綁定,因爲ContextMenu不在VisualTree中,因此無法看到您想要的元素。請使用Tag屬性並閱讀關於PlacementTarget的信息 - 明天我將向您發送一些代碼。 –

0

請設置您的DataTemplate以樹型視圖標記屬性。我有這樣的:

<DataTemplate> 
    <Grid Width="270" Height="20" Tag="{Binding DataContext, RelativeSource = {RelativeSource AncestorType={x:Type UserControl}}}"> 
      ... 
    <Grid.ContextMenu> 
      <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> 
       <MenuItem Header="Edit"> 
        <i:Interaction.Triggers> 
         <i:EventTrigger EventName="Click"> 
           <command:EventToCommand Command="{Binding Tag.YOURCOMMAND}"/> 
         </i:EventTrigger> 
        </i:Interaction.Triggers> 
        </MenuItem> 
      </ContextMenu> 
     </Grid.ContextMenu> 
    </Grid> 
</DataTemplate> 

它應該工作。

相關問題