ale*_*2k8 94 wpf treeview contextmenu
我想在显示ContextMenu之前右键单击选择一个WPF TreeView节点.
对于WinForms,我可以使用这样的代码在上下文菜单下点击查找节点,WPF的替代方案是什么?
ale*_*2k8 127
根据树的填充方式,发送方和e.Source值可能会有所不同.
其中一个可能的解决方案是使用e.OriginalSource并使用VisualTreeHelper查找TreeViewItem:
private void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject);
if (treeViewItem != null)
{
treeViewItem.Focus();
e.Handled = true;
}
}
static TreeViewItem VisualUpwardSearch(DependencyObject source)
{
while (source != null && !(source is TreeViewItem))
source = VisualTreeHelper.GetParent(source);
return source as TreeViewItem;
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*age 21
如果您想要一个仅限XAML的解决方案,您可以使用Blend Interactivity.
假设TreeView
数据绑定到具有Boolean
属性IsSelected
和String
属性的视图模型的分层集合Name
以及命名的子项集合Children
.
<TreeView ItemsSource="{Binding Items}">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseRightButtonDown">
<ei:ChangePropertyAction PropertyName="IsSelected" Value="true" TargetObject="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Run Code Online (Sandbox Code Playgroud)
有两个有趣的部分:
该TreeViewItem.IsSelected
属性IsSelected
与视图模型上的属性绑定.将IsSelected
view-model上的属性设置为true将选择树中的相应节点.
当PreviewMouseRightButtonDown
触发节点的可视部分时(在此示例a中TextBlock
)IsSelected
,视图模型上的属性设置为true.回到1.您可以看到在树中单击的相应节点成为选定节点.
在项目中获得Blend Interactivity的一种方法是使用NuGet包Unofficial.Blend.Interactivity.
Sea*_*all 12
使用alex2k8的原创想法,正确处理来自Wieser Software Ltd的非可视化,来自Stefan的XAML,来自Erlend的IsSelected,以及我对真正制作静态方法Generic的贡献:
XAML:
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<!-- We have to select the item which is right-clicked on -->
<EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown"
Handler="TreeViewItem_PreviewMouseRightButtonDown"/>
</Style>
</TreeView.ItemContainerStyle>
Run Code Online (Sandbox Code Playgroud)
C#代码背后:
void TreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TreeViewItem treeViewItem =
VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject);
if(treeViewItem != null)
{
treeViewItem.IsSelected = true;
e.Handled = true;
}
}
static T VisualUpwardSearch<T>(DependencyObject source) where T : DependencyObject
{
DependencyObject returnVal = source;
while(returnVal != null && !(returnVal is T))
{
DependencyObject tempReturnVal = null;
if(returnVal is Visual || returnVal is Visual3D)
{
tempReturnVal = VisualTreeHelper.GetParent(returnVal);
}
if(tempReturnVal == null)
{
returnVal = LogicalTreeHelper.GetParent(returnVal);
}
else returnVal = tempReturnVal;
}
return returnVal as T;
}
Run Code Online (Sandbox Code Playgroud)
编辑:以前的代码总是适用于这种情况,但在另一种情况下,当LogicalTreeHelper返回一个值时,VisualTreeHelper.GetParent返回null,因此修复了该问题.
Ste*_*fan 11
在XAML中,在XAML中添加PreviewMouseRightButtonDown处理程序:
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<!-- We have to select the item which is right-clicked on -->
<EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown"/>
</Style>
</TreeView.ItemContainerStyle>
Run Code Online (Sandbox Code Playgroud)
然后像这样处理事件:
private void TreeViewItem_PreviewMouseRightButtonDown( object sender, MouseEventArgs e )
{
TreeViewItem item = sender as TreeViewItem;
if ( item != null )
{
item.Focus( );
e.Handled = true;
}
}
Run Code Online (Sandbox Code Playgroud)
几乎是正确的,但你需要注意树中的非视觉效果(例如Run
,像a ).
static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
while (source != null && source.GetType() != typeof(T))
{
if (source is Visual || source is Visual3D)
{
source = VisualTreeHelper.GetParent(source);
}
else
{
source = LogicalTreeHelper.GetParent(source);
}
}
return source;
}
Run Code Online (Sandbox Code Playgroud)
我认为注册一个类处理程序应该可以解决问题.只需在app.xaml.cs代码文件中的TreeViewItem的PreviewMouseRightButtonDownEvent上注册一个路由事件处理程序,如下所示:
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(TreeViewItem), TreeViewItem.PreviewMouseRightButtonDownEvent, new RoutedEventHandler(TreeViewItem_PreviewMouseRightButtonDownEvent));
base.OnStartup(e);
}
private void TreeViewItem_PreviewMouseRightButtonDownEvent(object sender, RoutedEventArgs e)
{
(sender as TreeViewItem).IsSelected = true;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
57253 次 |
最近记录: |