我的Node
课程:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
namespace FrontEnd
{
public enum NodeType
{
SQLite,
Database,
TableCollection,
ViewCollection,
IndexCollection,
TriggerCollection,
ColumnCollection,
Table,
View,
Column,
Index,
Trigger
}
public class Node
{
public string Title { get; protected set; }
public NodeType Type { get; protected set; }
public ObservableCollection<Node> Nodes { get; set; }
public Node(string title, NodeType type)
{
this.Title = title;
this.Type = type;
this.Nodes = new ObservableCollection<Node>();
}
}
}
我的XAML:
<TreeView Name="dbTree" Padding="0,5,0,0">
<TreeView.Resources>
<ContextMenu x:Key="ScaleCollectionPopup">
<MenuItem Header="New Scale..."/>
</ContextMenu>
<ContextMenu x:Key="ScaleItemPopup">
<MenuItem Header="Remove Scale"/>
</ContextMenu>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource Self}}" Value="NodeType.Column">
<Setter Property="ContextMenu" Value="{StaticResource ScaleItemPopup}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Nodes}">
<StackPanel Orientation="Horizontal" Margin="0,0,0,4">
<Image Source="{Binding Converter={StaticResource StringToImageConverter}}" />
<TextBlock Text="{Binding Title}" Padding="5,0,0,0" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
我想要实现和失败的是根据绑定的ContextMenu
类的Type
属性决定使用Node
。
如果它是一个表或视图我想显示&#34; SELECT 1000 ROWS&#34; &安培; &#34; SHOW CREATE SQL&#34;,对于其他类型,我想定义其他选项。
达到预期效果的正确方法是什么?
答案 0 :(得分:1)
当每个节点的视图模型生成上下文菜单时,我更喜欢以mvvm样式执行此操作。请参阅以下示例:
查看部分:
<Window x:Class="WpfApplication1.MainWindow"
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:wpfApplication1="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
d:DataContext="{d:DesignInstance wpfApplication1:ViewModel}">
<Grid>
<TreeView ItemsSource="{Binding Path=Nodes}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Nodes}">
<StackPanel>
<StackPanel.ContextMenu>
<ContextMenu ItemsSource="{Binding ContextMenu}">
<ContextMenu.Resources>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding Command}"/>
</Style>
</ContextMenu.Resources>
<ContextMenu.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Title}"/>
</HierarchicalDataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock Text="{Binding Title}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
查看模型部分:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
public class MenuItem
{
public MenuItem()
{
Items = new ObservableCollection<MenuItem>();
}
public string Title { get; set; }
public ICommand Command { get; set; }
public ObservableCollection<MenuItem> Items { get; private set; }
}
public class ViewModel
{
public ViewModel()
{
Nodes = new ObservableCollection<Node>
{
new Node("MSSQL", NodeType.Database,
new Node("Customers", NodeType.Table)),
new Node("Oracle", NodeType.Database)
};
}
public ObservableCollection<Node> Nodes { get; set; }
}
public enum NodeType
{
Database,
Table,
}
public class Node
{
public string Title { get; protected set; }
public NodeType Type { get; protected set; }
public ObservableCollection<Node> Nodes { get; set; }
public Node(string title, NodeType type, params Node[] nodes)
{
this.Title = title;
this.Type = type;
this.Nodes = new ObservableCollection<Node>();
if (nodes != null)
nodes.ToList().ForEach(this.Nodes.Add);
}
public IEnumerable<MenuItem> ContextMenu
{
get { return createMenu(this); }
}
private static IEnumerable<MenuItem> createMenu(Node node)
{
switch (node.Type)
{
case NodeType.Database:
return new List<MenuItem>
{
new MenuItem {Title = "Create table...", Command = new RelayCommand(o => MessageBox.Show("Table created"))}
};
case NodeType.Table:
return new List<MenuItem>
{
new MenuItem {Title = "Select..."},
new MenuItem {Title = "Edit..."}
};
default:
return null;
}
}
}
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(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 || _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion // ICommand Members
}
(你可以使用任何实现ICommand接口,RelayCommand就是其中之一) 您可以在Node类或IContextMenuBuilder服务中生成可以传递给Node构造函数的菜单项。