[英]Custom Treeview User Control MVVM Double Click Bubbling Event WPF
I'm trying to make a custom TreeView and make it a user control.我正在尝试制作自定义 TreeView 并使其成为用户控件。 When I wrap the user control in another window, I tried to get the TreeView item double click event in the main window.
当我将用户控件包装在另一个窗口中时,我试图在主窗口中获取 TreeView 项目双击事件。
<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>
I tried to get the bubbling mouse double click from CustomTreeView item and intercept the event in the grid wrapper outside the usercontrol.我试图从 CustomTreeView 项目中获取冒泡鼠标双击,并在用户控件外的网格包装器中拦截事件。 I tried to add TreeViewItem.
我试图添加 TreeViewItem。 TreeViewItem.MouseLeftButtonDown="Grid_MouseLeftButtonDown and failed. Any ideas to solve my problem?
TreeViewItem.MouseLeftButtonDown="Grid_MouseLeftButtonDown 失败了。有什么办法可以解决我的问题吗?
Here is my code of custom user control for treeview这是我的树视图自定义用户控件代码
<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>
You don't need to publish double-click event outside from the user control at all.您根本不需要在用户控件之外发布双击事件。 You need to add some
InputBinding
( MouseBinding
in this particular case) into InputBindings
collection of the TreeView.SelectedItem
.您需要将一些
InputBinding
(在此特定情况下为MouseBinding
)添加到TreeView.SelectedItem
的InputBindings
集合中。
The problem is that you can't do that in normal, obvious way - set InputBindings
via TreeView.ItemContainerStyle
, because InputBindings
collection is read-only.问题是你不能以正常、明显的方式做到这一点——通过
TreeView.ItemContainerStyle
设置InputBindings
,因为InputBindings
集合是只读的。 Sad, but true.悲伤,但真实。
Good news is that you can use attached property to accomplish that.好消息是您可以使用附加属性来实现这一点。 The sample:
例子:
View models.查看模型。
a) this is what will be displayed as items in tree view: a) 这是将在树视图中显示为项目的内容:
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) this is "main" view model: 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;
}
User control code-behind.用户控制代码隐藏。 Basic idea - we're adding one attached property to set input binding though it in XAML, and another one - to allow external world bind command, when input binding fires:
基本思想——我们添加一个附加属性来通过它在 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);
}
}
}
}
User control XAML:用户控制 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>
Main window XAML:主窗口 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>
Main window code-behind:主窗口代码隐藏:
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"},
}
},
}
};
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.