2012-08-13 156 views
2

我正在嘗試使自定義TreeView,並使其成爲用戶控件。當我將用戶控件包裝在另一個窗口中時,我嘗試在主窗口中獲取TreeView項雙擊事件。自定義TreeView用戶控件MVVM雙擊冒泡事件WPF

<Window xmlns:avalondock="http://avalondock.codeplex.com"  x:Class="WellsVisualizationWPF.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:well="clr-namespace:VisualizationWPF.ViewModel.ViewUserControl" 
    Title="e-IFD" Height="408" Width="558" WindowState="Maximized" 
    > 
<Grid MinWidth="100" **TreeViewItem.MouseLeftButtonClick=<EventHandler>**> <-- Trying to override but failed :p           
    <local:CustomTreeView /> 
</Grid> 

我試圖讓從CustomTreeView項目冒泡鼠標雙擊並在用戶控件外電網包裝截獲該事件。我試圖添加TreeViewItem。 TreeViewItem.MouseLeftButtonDown =「Grid_MouseLeftButtonDown和失敗。任何想法來解決我的問題?

這裏是我的樹視圖自定義用戶控件的代碼

<UserControl x:Class="WellsVisualizationWPF.ViewModel.ViewUserControl.WellsTreeView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   
     xmlns:local="clr-namespace:VisualizationWPF.ViewModel"   
     > 
<Grid MinWidth="100"> 
    <Grid.RowDefinitions> 
     <RowDefinition MaxHeight="500" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <StackPanel Grid.Row="1"> 
     <TextBlock TextWrapping="Wrap" FontSize="12"> 
     Text1 
     </TextBlock> 
     <Button Height="24" Content="Add New" Name="btn_add" Click="btn_add_Click" /> 
    </StackPanel> 
    <ScrollViewer> 
     <DockPanel> 
      <TreeView Grid.Row="0" ItemsSource="{Binding Data}"> 
       <TreeView.Resources> 
        <HierarchicalDataTemplate 
        DataType="{x:Type local:MainViewModel}" 
        ItemsSource="{Binding Children}" 
        > 
         <StackPanel Orientation="Horizontal"> 
          <TextBlock Text="{Binding Name}" /> 
         </StackPanel> 
        </HierarchicalDataTemplate> 
        <DataTemplate DataType="{x:Type local:ParamsViewModel}"> 
         <TextBlock Text="{Binding Name}" />        
        </DataTemplate> 
       </TreeView.Resources>      
      </TreeView> 
     </DockPanel> 
    </ScrollViewer> 
</Grid> 

+0

您是否想從外部雙擊'Treeview'中的選定項目來執行命令? – Dennis 2012-08-13 06:54:31

+0

是的,完全如此,有什麼想法? – euclid135 2012-08-13 12:51:00

+0

添加了答案。 – Dennis 2012-08-13 13:18:30

回答

2

你並不需要發佈雙單擊事件外,從用戶控制的。 您需要添加一些InputBindingMouseBinding在這種特殊情況下)爲InputBindings收集TreeView.SelectedItem的。

問題是,你不能以正常,明顯的方式做到這一點 - 通過TreeView.ItemContainerStyle設置InputBindings,因爲InputBindings集合是隻讀的。傷心,但是真的。

好消息是,您可以使用附加屬性來完成該操作。 樣本:

查看模型。
一)這是將顯示在樹視圖中的項目:

public class Node : ViewModelBase 
{ 
    public String Text 
    { 
     get { return text; } 
     set 
     { 
      if (text != value) 
      { 
       text = value; 
       OnPropertyChanged("Text"); 
      } 
     } 
    } 
    private String text; 

    public ObservableCollection<Node> Nodes { get; set; } 
} 

b)本是「主」視圖模型:

public class ViewModel : ViewModelBase 
{ 
    public ViewModel() 
    { 
     this.selectedNodeDoubleClickedCommand = new RelayCommand<Node>(node => 
     { 
      Debug.WriteLine(String.Format("{0} clicked!", node.Text)); 
     }); 
    } 

    public ObservableCollection<Node> Nodes { get; set; } 

    public RelayCommand<Node> SelectedNodeDoubleClickedCommand 
    { 
     get { return selectedNodeDoubleClickedCommand; } 
    } 
    private readonly RelayCommand<Node> selectedNodeDoubleClickedCommand; 
} 

用戶控件的代碼隱藏。基本思想 - 我們增加一個附加屬性來設置輸入XAML雖然結合,而另一個 - 允許外界綁定命令,當輸入綁定火災:

public partial class UserControl1 : UserControl 
{ 
    public UserControl1() 
    { 
     InitializeComponent(); 
    } 

    public ICommand SelectedItemDoubleClickedCommand 
    { 
     get { return (ICommand)GetValue(SelectedItemDoubleClickedCommandProperty); } 
     set { SetValue(SelectedItemDoubleClickedCommandProperty, value); } 
    } 

    public static readonly DependencyProperty SelectedItemDoubleClickedCommandProperty = DependencyProperty.Register(
     "SelectedItemDoubleClickedCommand", typeof(ICommand), 
     typeof(UserControl1), 
     new UIPropertyMetadata(null)); 

    public static ICommand GetSelectedItemDoubleClickedCommandAttached(DependencyObject obj) 
    { 
     return (ICommand)obj.GetValue(SelectedItemDoubleClickedCommandAttachedProperty); 
    } 

    public static void SetSelectedItemDoubleClickedCommandAttached(DependencyObject obj, ICommand value) 
    { 
     obj.SetValue(SelectedItemDoubleClickedCommandAttachedProperty, value); 
    } 

    public static readonly DependencyProperty SelectedItemDoubleClickedCommandAttachedProperty = DependencyProperty.RegisterAttached(
     "SelectedItemDoubleClickedCommandAttached", 
     typeof(ICommand), typeof(UserControl1), 
     new UIPropertyMetadata(null, SelectedItemDoubleClickedCommandAttachedChanged)); 

    private static void SelectedItemDoubleClickedCommandAttachedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var item = d as TreeViewItem; 
     if (item != null) 
     { 
      if (e.NewValue != null) 
      { 
       var binding = new MouseBinding((ICommand)e.NewValue, new MouseGesture(MouseAction.LeftDoubleClick)); 

       BindingOperations.SetBinding(binding, InputBinding.CommandParameterProperty, new Binding("SelectedItem") 
       { 
        RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(TreeView), 1) 
       }); 

       item.InputBindings.Add(binding); 
      } 
     } 
    } 
} 

用戶控制XAML:

<Grid> 
    <TreeView ItemsSource="{Binding Nodes}"> 
     <TreeView.Resources> 
      <HierarchicalDataTemplate ItemsSource="{Binding Nodes}" DataType="{x:Type local:Node}"> 
       <TextBlock Text="{Binding Text}"/> 
      </HierarchicalDataTemplate> 
     </TreeView.Resources> 
     <TreeView.ItemContainerStyle> 
      <Style TargetType="{x:Type TreeViewItem}"> 
       <Setter Property="local:UserControl1.SelectedItemDoubleClickedCommandAttached" 
         Value="{Binding SelectedItemDoubleClickedCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" /> 
      </Style> 
     </TreeView.ItemContainerStyle> 

    </TreeView> 
</Grid> 

主窗口XAML:

<Window x:Class="WpfApplication2.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication2" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <local:UserControl1 SelectedItemDoubleClickedCommand="{Binding SelectedNodeDoubleClickedCommand}"/> 
    </Grid> 
</Window> 

主窗口代碼隱藏:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new ViewModel 
     { 
      Nodes = new ObservableCollection<Node> 
      { 
       new Node 
       { 
        Text = "Parent 1", 
        Nodes = new ObservableCollection<Node> 
        { 
         new Node { Text = "Child 1.1"}, 
         new Node { Text = "Child 1.2"}, 
        } 
       }, 
       new Node 
       { 
        Text = "Parent 2", 
        Nodes = new ObservableCollection<Node> 
        { 
         new Node { Text = "Child 2.1"}, 
         new Node { Text = "Child 2.2"}, 
        } 
       }, 
      } 
     }; 
    } 
}