Mind Editoe

This commit is contained in:
艾竹
2023-03-05 21:30:53 +08:00
parent 9061146139
commit 79f4896fbd
41 changed files with 2090 additions and 484 deletions

View File

@@ -0,0 +1,171 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:AIStudio.Wpf.Mind.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Mind;component/Styles/Button.xaml" />
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Mind;component/Styles/ContextMenu.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="AIStudio.Styles.DropDownButton" TargetType="{x:Type controls:DropDownButton}">
<Setter Property="ArrowBrush" Value="Black" />
<Setter Property="ArrowMouseOverBrush"
Value="{Binding Foreground, RelativeSource={RelativeSource Mode=Self},
Converter={StaticResource BrushOpacityConverter}, ConverterParameter=0.16}" />
<Setter Property="ArrowPressedBrush" Value="Black" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="ButtonStyle" Value="{StaticResource FlatButtonStyle}" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="MenuStyle" Value="{StaticResource ContextMenuStyle}" />
<Setter Property="MinHeight" Value="26" />
<Setter Property="Padding" Value="3" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:DropDownButton}">
<Grid>
<Border x:Name="PART_Border"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="3"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
UseLayoutRounding="True">
<Button x:Name="PART_Button"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
FocusVisualStyle="{TemplateBinding FocusVisualStyle}"
Foreground="{TemplateBinding Foreground}"
RenderOptions.ClearTypeHint="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(RenderOptions.ClearTypeHint), Mode=OneWay}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Style="{TemplateBinding ButtonStyle}">
<DockPanel x:Name="PART_Content"
Focusable="False"
LastChildFill="True">
<!-- Material - ChevronDown -->
<Path x:Name="PART_Arrow"
Width="9"
Height="6"
Margin="0 0 3 0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z"
DockPanel.Dock="Right"
Stretch="Fill"
Fill="{TemplateBinding ArrowBrush}"
Visibility="{TemplateBinding ArrowVisibility}" />
<StackPanel x:Name="PART_ContentOrientation"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Focusable="False"
Orientation="Horizontal">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Icon}"
ContentTemplate="{TemplateBinding IconTemplate}"
Focusable="False"
RecognizesAccessKey="True"
UseLayoutRounding="False" />
<ContentControl x:Name="PART_ButtonContent"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{Binding Content, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
UseLayoutRounding="False" />
</StackPanel>
</DockPanel>
<Button.ContextMenu>
<ContextMenu x:Name="PART_Menu"
MinWidth="{TemplateBinding ActualWidth}"
DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
GroupStyleSelector="{TemplateBinding GroupStyleSelector}"
IsOpen="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
ItemContainerStyleSelector="{TemplateBinding ItemContainerStyleSelector}"
ItemStringFormat="{TemplateBinding ItemStringFormat}"
ItemTemplate="{TemplateBinding ItemTemplate}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
ItemsPanel="{TemplateBinding ItemsPanel}"
ItemsSource="{TemplateBinding ItemsSource}"
Placement="Bottom"
StaysOpen="False"
Style="{TemplateBinding MenuStyle}"
UseLayoutRounding="False" />
</Button.ContextMenu>
</Button>
</Border>
<!--<Popup x:Name="PART_Popup"
Placement="Bottom"
IsOpen="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
AllowsTransparency="True"
Margin="0,0,-4,0">
<Border>
<ScrollViewer x:Name="PART_ScrollViewer"
IsTabStop="False"
Margin="1"
SnapsToDevicePixels="True"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Hidden">
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Local" />
</ScrollViewer>
</Border>
</Popup>-->
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Content" Value="{x:Null}">
<Setter TargetName="PART_ButtonContent" Property="Margin" Value="0" />
</Trigger>
<Trigger Property="Orientation" Value="Vertical">
<Setter TargetName="PART_Arrow" Property="DockPanel.Dock" Value="Bottom" />
<Setter TargetName="PART_Arrow" Property="Margin" Value="0 0 0 3" />
<Setter TargetName="PART_ContentOrientation" Property="Orientation" Value="Vertical" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition SourceName="PART_Button" Property="IsEnabled" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Arrow" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ArrowMouseOverBrush, Mode=OneWay}" />
</MultiTrigger>
<Trigger SourceName="PART_Button" Property="IsPressed" Value="True">
<Setter TargetName="PART_Arrow" Property="Fill" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ArrowPressedBrush, Mode=OneWay}" />
</Trigger>
<Trigger SourceName="PART_Button" Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value=".55" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="VerticalContentAlignment" Value="Center" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" Value="LightGray" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="LightGray" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value=".55" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type controls:DropDownButton}" BasedOn="{StaticResource AIStudio.Styles.DropDownButton}" />
</ResourceDictionary>

View File

@@ -0,0 +1,685 @@
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
namespace AIStudio.Wpf.Mind.Controls
{
[ContentProperty(nameof(ItemsSource))]
[TemplatePart(Name = "PART_Button", Type = typeof(Button))]
[TemplatePart(Name = "PART_ButtonContent", Type = typeof(ContentControl))]
[TemplatePart(Name = "PART_Menu", Type = typeof(ContextMenu))]
[StyleTypedProperty(Property = nameof(ButtonStyle), StyleTargetType = typeof(Button))]
[StyleTypedProperty(Property = nameof(MenuStyle), StyleTargetType = typeof(ContextMenu))]
public class DropDownButton : ItemsControl, ICommandSource
{
public static readonly RoutedEvent ClickEvent
= EventManager.RegisterRoutedEvent(nameof(Click),
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(DropDownButton));
public event RoutedEventHandler Click
{
add => this.AddHandler(ClickEvent, value);
remove => this.RemoveHandler(ClickEvent, value);
}
/// <summary>Identifies the <see cref="IsExpanded"/> dependency property.</summary>
public static readonly DependencyProperty IsExpandedProperty
= DependencyProperty.Register(nameof(IsExpanded),
typeof(bool),
typeof(DropDownButton),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsExpandedPropertyChangedCallback));
private static void OnIsExpandedPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
if (dependencyObject is DropDownButton dropDownButton
&& !(dropDownButton.contextMenu == null))
{
dropDownButton.SetContextMenuPlacementTarget(dropDownButton.contextMenu);
}
}
protected virtual void SetContextMenuPlacementTarget(ContextMenu contextMenu)
{
if (this.button != null)
{
contextMenu.PlacementTarget = this.button;
}
}
/// <summary>
/// Whether or not the "popup" menu for this control is currently open
/// </summary>
public bool IsExpanded
{
get => (bool)this.GetValue(IsExpandedProperty);
set => this.SetValue(IsExpandedProperty, (bool)value);
}
/// <summary>Identifies the <see cref="ExtraTag"/> dependency property.</summary>
public static readonly DependencyProperty ExtraTagProperty
= DependencyProperty.Register(nameof(ExtraTag),
typeof(object),
typeof(DropDownButton));
/// <summary>
/// Gets or sets an extra tag.
/// </summary>
public object ExtraTag
{
get => this.GetValue(ExtraTagProperty);
set => this.SetValue(ExtraTagProperty, value);
}
/// <summary>Identifies the <see cref="Orientation"/> dependency property.</summary>
public static readonly DependencyProperty OrientationProperty
= DependencyProperty.Register(nameof(Orientation),
typeof(Orientation),
typeof(DropDownButton),
new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the orientation of children stacking.
/// </summary>
public Orientation Orientation
{
get => (Orientation)this.GetValue(OrientationProperty);
set => this.SetValue(OrientationProperty, value);
}
/// <summary>Identifies the <see cref="Icon"/> dependency property.</summary>
public static readonly DependencyProperty IconProperty
= DependencyProperty.Register(nameof(Icon),
typeof(object),
typeof(DropDownButton));
/// <summary>
/// Gets or sets the content for the icon part.
/// </summary>
[Bindable(true)]
public object Icon
{
get => this.GetValue(IconProperty);
set => this.SetValue(IconProperty, value);
}
/// <summary>Identifies the <see cref="IconTemplate"/> dependency property.</summary>
public static readonly DependencyProperty IconTemplateProperty
= DependencyProperty.Register(nameof(IconTemplate),
typeof(DataTemplate),
typeof(DropDownButton));
/// <summary>
/// Gets or sets the DataTemplate for the icon part.
/// </summary>
[Bindable(true)]
public DataTemplate IconTemplate
{
get => (DataTemplate)this.GetValue(IconTemplateProperty);
set => this.SetValue(IconTemplateProperty, value);
}
/// <summary>Identifies the <see cref="Command"/> dependency property.</summary>
public static readonly DependencyProperty CommandProperty
= DependencyProperty.Register(nameof(Command),
typeof(ICommand),
typeof(DropDownButton),
new PropertyMetadata(null, OnCommandPropertyChangedCallback));
private static void OnCommandPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
(dependencyObject as DropDownButton).OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue);
}
/// <summary>
/// Gets or sets the command to invoke when the content button is pressed.
/// </summary>
public ICommand Command
{
get => (ICommand)this.GetValue(CommandProperty);
set => this.SetValue(CommandProperty, value);
}
/// <summary>Identifies the <see cref="CommandTarget"/> dependency property.</summary>
public static readonly DependencyProperty CommandTargetProperty
= DependencyProperty.Register(nameof(CommandTarget),
typeof(IInputElement),
typeof(DropDownButton),
new PropertyMetadata(null));
/// <summary>
/// Gets or sets the element on which to raise the specified command.
/// </summary>
public IInputElement CommandTarget
{
get => (IInputElement)this.GetValue(CommandTargetProperty);
set => this.SetValue(CommandTargetProperty, value);
}
/// <summary>Identifies the <see cref="CommandParameter"/> dependency property.</summary>
public static readonly DependencyProperty CommandParameterProperty
= DependencyProperty.Register(nameof(CommandParameter),
typeof(object),
typeof(DropDownButton),
new PropertyMetadata(null));
/// <summary>
/// Gets or sets the parameter to pass to the command property.
/// </summary>
public object CommandParameter
{
get => (object)this.GetValue(CommandParameterProperty);
set => this.SetValue(CommandParameterProperty, value);
}
/// <summary>Identifies the <see cref="Content"/> dependency property.</summary>
public static readonly DependencyProperty ContentProperty
= DependencyProperty.Register(nameof(Content),
typeof(object),
typeof(DropDownButton));
/// <summary>
/// Gets or sets the content of this control.
/// </summary>
public object Content
{
get => (object)this.GetValue(ContentProperty);
set => this.SetValue(ContentProperty, value);
}
/// <summary>Identifies the <see cref="ContentTemplate"/> dependency property.</summary>
public static readonly DependencyProperty ContentTemplateProperty
= DependencyProperty.Register(nameof(ContentTemplate),
typeof(DataTemplate),
typeof(DropDownButton),
new FrameworkPropertyMetadata(null));
/// <summary>
/// Gets or sets the data template used to display the content of the DropDownButton.
/// </summary>
[Bindable(true)]
public DataTemplate ContentTemplate
{
get => (DataTemplate)this.GetValue(ContentTemplateProperty);
set => this.SetValue(ContentTemplateProperty, value);
}
/// <summary>Identifies the <see cref="ContentTemplateSelector"/> dependency property.</summary>
public static readonly DependencyProperty ContentTemplateSelectorProperty
= DependencyProperty.Register(nameof(ContentTemplateSelector),
typeof(DataTemplateSelector),
typeof(DropDownButton),
new FrameworkPropertyMetadata(null));
/// <summary>
/// Gets or sets a template selector that enables an application writer to provide custom template-selection logic.
/// </summary>
/// <remarks>
/// This property is ignored if <seealso cref="ContentTemplate"/> is set.
/// </remarks>
[Bindable(true)]
public DataTemplateSelector ContentTemplateSelector
{
get => (DataTemplateSelector)this.GetValue(ContentTemplateSelectorProperty);
set => this.SetValue(ContentTemplateSelectorProperty, value);
}
/// <summary>Identifies the <see cref="ContentStringFormat"/> dependency property.</summary>
public static readonly DependencyProperty ContentStringFormatProperty
= DependencyProperty.Register(nameof(ContentStringFormat),
typeof(string),
typeof(DropDownButton),
new FrameworkPropertyMetadata(null));
/// <summary>
/// Gets or sets a composite string that specifies how to format the content property if it is displayed as a string.
/// </summary>
/// <remarks>
/// This property is ignored if <seealso cref="ContentTemplate"/> is set.
/// </remarks>
[Bindable(true)]
public string ContentStringFormat
{
get => (string)this.GetValue(ContentStringFormatProperty);
set => this.SetValue(ContentStringFormatProperty, value);
}
/// <summary>Identifies the <see cref="ButtonStyle"/> dependency property.</summary>
public static readonly DependencyProperty ButtonStyleProperty
= DependencyProperty.Register(nameof(ButtonStyle),
typeof(Style),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Style), FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the button content style.
/// </summary>
public Style ButtonStyle
{
get => (Style)this.GetValue(ButtonStyleProperty);
set => this.SetValue(ButtonStyleProperty, value);
}
/// <summary>Identifies the <see cref="MenuStyle"/> dependency property.</summary>
public static readonly DependencyProperty MenuStyleProperty
= DependencyProperty.Register(nameof(MenuStyle),
typeof(Style),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Style), FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the "popup" menu style.
/// </summary>
public Style MenuStyle
{
get => (Style)this.GetValue(MenuStyleProperty);
set => this.SetValue(MenuStyleProperty, value);
}
/// <summary>Identifies the <see cref="ArrowBrush"/> dependency property.</summary>
public static readonly DependencyProperty ArrowBrushProperty
= DependencyProperty.Register(nameof(ArrowBrush),
typeof(Brush),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Gets or sets the foreground brush for the button arrow icon.
/// </summary>
public Brush ArrowBrush
{
get => (Brush)this.GetValue(ArrowBrushProperty);
set => this.SetValue(ArrowBrushProperty, value);
}
/// <summary>Identifies the <see cref="ArrowMouseOverBrush"/> dependency property.</summary>
public static readonly DependencyProperty ArrowMouseOverBrushProperty
= DependencyProperty.Register(nameof(ArrowMouseOverBrush),
typeof(Brush),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Gets or sets the foreground brush of the button arrow icon if the mouse is over the drop down button.
/// </summary>
public Brush ArrowMouseOverBrush
{
get => (Brush)this.GetValue(ArrowMouseOverBrushProperty);
set => this.SetValue(ArrowMouseOverBrushProperty, value);
}
/// <summary>Identifies the <see cref="ArrowPressedBrush"/> dependency property.</summary>
public static readonly DependencyProperty ArrowPressedBrushProperty
= DependencyProperty.Register(nameof(ArrowPressedBrush),
typeof(Brush),
typeof(DropDownButton),
new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// Gets or sets the foreground brush of the button arrow icon if the arrow button is pressed.
/// </summary>
public Brush ArrowPressedBrush
{
get => (Brush)this.GetValue(ArrowPressedBrushProperty);
set => this.SetValue(ArrowPressedBrushProperty, value);
}
/// <summary>Identifies the <see cref="ArrowVisibility"/> dependency property.</summary>
public static readonly DependencyProperty ArrowVisibilityProperty
= DependencyProperty.Register(nameof(ArrowVisibility),
typeof(Visibility),
typeof(DropDownButton),
new FrameworkPropertyMetadata(Visibility.Visible, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Gets or sets the visibility of the button arrow icon.
/// </summary>
public Visibility ArrowVisibility
{
get => (Visibility)this.GetValue(ArrowVisibilityProperty);
set => this.SetValue(ArrowVisibilityProperty, value);
}
static DropDownButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DropDownButton), new FrameworkPropertyMetadata(typeof(DropDownButton)));
}
private void OnCommandChanged(ICommand oldCommand, ICommand newCommand)
{
if (oldCommand != null)
{
this.UnhookCommand(oldCommand);
}
if (newCommand != null)
{
this.HookCommand(newCommand);
}
}
private void UnhookCommand(ICommand command)
{
CanExecuteChangedEventManager.RemoveHandler(command, this.OnCanExecuteChanged);
this.UpdateCanExecute();
}
private void HookCommand(ICommand command)
{
CanExecuteChangedEventManager.AddHandler(command, this.OnCanExecuteChanged);
this.UpdateCanExecute();
}
private void OnCanExecuteChanged(object sender, EventArgs e)
{
this.UpdateCanExecute();
}
private void UpdateCanExecute()
{
this.CanExecute = this.Command == null || CommandHelpers.CanExecuteCommandSource(this);
}
/// <inheritdoc />
protected override bool IsEnabledCore => base.IsEnabledCore && this.CanExecute;
private bool canExecute = true;
private bool CanExecute
{
get => this.canExecute;
set
{
if (value == this.canExecute)
{
return;
}
this.canExecute = value;
this.CoerceValue(IsEnabledProperty);
}
}
private void ButtonClick(object sender, RoutedEventArgs e)
{
CommandHelpers.ExecuteCommandSource(this);
if (this.contextMenu?.HasItems == true)
{
this.SetCurrentValue(IsExpandedProperty, true);
}
e.RoutedEvent = ClickEvent;
this.RaiseEvent(e);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (this.button != null)
{
this.button.Click -= this.ButtonClick;
}
this.button = this.GetTemplateChild("PART_Button") as Button;
if (this.button != null)
{
this.button.Click += this.ButtonClick;
}
this.GroupStyle.CollectionChanged -= this.OnGroupStyleCollectionChanged;
this.contextMenu = this.GetTemplateChild("PART_Menu") as ContextMenu;
if (this.contextMenu != null)
{
foreach (var groupStyle in this.GroupStyle)
{
this.contextMenu.GroupStyle.Add(groupStyle);
}
this.GroupStyle.CollectionChanged += this.OnGroupStyleCollectionChanged;
if (this.Items != null && this.ItemsSource == null)
{
foreach (var newItem in this.Items)
{
this.TryRemoveVisualFromOldTree(newItem);
this.contextMenu.Items.Add(newItem);
}
}
}
}
#if NET5_0_OR_GREATER
private void OnGroupStyleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
#else
private void OnGroupStyleCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
#endif
{
if (e.OldItems != null)
{
foreach (var groupStyle in e.OldItems.OfType<GroupStyle>())
{
this.contextMenu?.GroupStyle.Remove(groupStyle);
}
}
if (e.NewItems != null)
{
foreach (var groupStyle in e.NewItems.OfType<GroupStyle>())
{
this.contextMenu?.GroupStyle.Add(groupStyle);
}
}
}
/// <inheritdoc />
protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
{
base.OnMouseRightButtonUp(e);
e.Handled = true;
}
private void TryRemoveVisualFromOldTree(object item)
{
if (item is Visual visual)
{
var parent = LogicalTreeHelper.GetParent(visual) as FrameworkElement ?? VisualTreeHelper.GetParent(visual) as FrameworkElement;
if (Equals(this, parent))
{
this.RemoveLogicalChild(visual);
this.RemoveVisualChild(visual);
}
}
}
/// <summary>Invoked when the <see cref="P:System.Windows.Controls.ItemsControl.Items" /> property changes.</summary>
/// <param name="e">Information about the change.</param>
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
if (this.contextMenu == null || this.ItemsSource != null || this.contextMenu.ItemsSource != null)
{
return;
}
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
if (e.NewItems != null)
{
foreach (var newItem in e.NewItems)
{
this.TryRemoveVisualFromOldTree(newItem);
this.contextMenu.Items.Add(newItem);
}
}
break;
case NotifyCollectionChangedAction.Remove:
if (e.OldItems != null)
{
foreach (var oldItem in e.OldItems)
{
this.contextMenu.Items.Remove(oldItem);
}
}
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
if (e.OldItems != null)
{
foreach (var oldItem in e.OldItems)
{
this.contextMenu.Items.Remove(oldItem);
}
}
if (e.NewItems != null)
{
foreach (var newItem in e.NewItems)
{
this.TryRemoveVisualFromOldTree(newItem);
this.contextMenu.Items.Add(newItem);
}
}
break;
case NotifyCollectionChangedAction.Reset:
if (this.Items != null)
{
this.contextMenu.Items.Clear();
foreach (var newItem in this.Items)
{
this.TryRemoveVisualFromOldTree(newItem);
this.contextMenu.Items.Add(newItem);
}
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private Button button;
private ContextMenu contextMenu;
}
internal static class CommandHelpers
{
internal static bool CanExecuteCommandSource(ICommandSource commandSource)
{
var command = commandSource.Command;
if (command == null)
{
return false;
}
var commandParameter = commandSource.CommandParameter ?? commandSource;
if (command is RoutedCommand routedCommand)
{
var target = commandSource.CommandTarget ?? commandSource as IInputElement;
return routedCommand.CanExecute(commandParameter, target);
}
return command.CanExecute(commandParameter);
}
[SecurityCritical]
[SecuritySafeCritical]
internal static void ExecuteCommandSource(ICommandSource commandSource)
{
CriticalExecuteCommandSource(commandSource);
}
[SecurityCritical]
internal static void CriticalExecuteCommandSource(ICommandSource commandSource)
{
var command = commandSource.Command;
if (command == null)
{
return;
}
var commandParameter = commandSource.CommandParameter ?? commandSource;
if (command is RoutedCommand routedCommand)
{
var target = commandSource.CommandTarget ?? commandSource as IInputElement;
if (routedCommand.CanExecute(commandParameter, target))
{
routedCommand.Execute(commandParameter, target);
}
}
else
{
if (command.CanExecute(commandParameter))
{
command.Execute(commandParameter);
}
}
}
internal static bool CanExecuteCommandSource(ICommandSource commandSource, ICommand theCommand)
{
var command = theCommand;
if (command == null)
{
return false;
}
var commandParameter = commandSource.CommandParameter ?? commandSource;
if (command is RoutedCommand routedCommand)
{
var target = commandSource.CommandTarget ?? commandSource as IInputElement;
return routedCommand.CanExecute(commandParameter, target);
}
return command.CanExecute(commandParameter);
}
[SecurityCritical]
[SecuritySafeCritical]
internal static void ExecuteCommandSource(ICommandSource commandSource, ICommand theCommand)
{
CriticalExecuteCommandSource(commandSource, theCommand);
}
[SecurityCritical]
internal static void CriticalExecuteCommandSource(ICommandSource commandSource, ICommand theCommand)
{
var command = theCommand;
if (command == null)
{
return;
}
var commandParameter = commandSource.CommandParameter ?? commandSource;
if (command is RoutedCommand routedCommand)
{
var target = commandSource.CommandTarget ?? commandSource as IInputElement;
if (routedCommand.CanExecute(commandParameter, target))
{
routedCommand.Execute(commandParameter, target);
}
}
else
{
if (command.CanExecute(commandParameter))
{
command.Execute(commandParameter);
}
}
}
}
}

View File

@@ -20,7 +20,7 @@
<!-- ToolBox Control -->
<ContentControl Template="{Binding ToolBox,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
<ScrollViewer Grid.Column="1">
<ScrollViewer Grid.Row="1">
<!-- Diagram Control -->
<dd:DiagramControl x:Name="PART_DiagramControl" MinWidth="1000" MinHeight="1000" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</ScrollViewer>

View File

@@ -10,6 +10,7 @@ using System.Windows;
using System.Xml.Linq;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.Mind.ViewModels;
namespace AIStudio.Wpf.Mind.Controls
{
@@ -22,7 +23,7 @@ namespace AIStudio.Wpf.Mind.Controls
public const string PART_DiagramControl = "PART_DiagramControl";
private DiagramControl _diagramControl;
private IDiagramViewModel _diagramViewModel;
private MindDiagramViewModel _diagramViewModel;
static MindEditor()
{
@@ -31,16 +32,10 @@ namespace AIStudio.Wpf.Mind.Controls
public MindEditor()
{
_diagramViewModel = new DiagramViewModel();
_diagramViewModel.ShowGrid = true;
_diagramViewModel.GridCellSize = new SizeBase(125 / ScreenHelper.ScreenScale, 125 / ScreenHelper.ScreenScale);
_diagramViewModel = new MindDiagramViewModel();
_diagramViewModel.GridMarginSize = new Size(0, 0);
_diagramViewModel.CellHorizontalAlignment = CellHorizontalAlignment.Center;
_diagramViewModel.CellVerticalAlignment = CellVerticalAlignment.Center;
_diagramViewModel.PageSizeType = PageSizeType.Custom;
_diagramViewModel.PageSize = new SizeBase(double.NaN, double.NaN);
_diagramViewModel.ColorViewModel = new ColorViewModel() { LineWidth = 2 };
_diagramViewModel.DrawModeViewModel = new DrawModeViewModel() { LineDrawMode = DrawMode.ConnectingLineSmooth };
_diagramViewModel.PropertyChanged += DiagramViewModel_PropertyChanged;
}
@@ -52,7 +47,7 @@ namespace AIStudio.Wpf.Mind.Controls
_diagramControl = GetTemplateChild(PART_DiagramControl) as DiagramControl;
_diagramControl.HorizontalAlignment = HorizontalAlignment.Stretch;
_diagramControl.VerticalAlignment = VerticalAlignment.Stretch;
_diagramControl.DataContext = _diagramViewModel;
this.DataContext = _diagramViewModel;
GetDataFunc = GetData;
}
@@ -97,7 +92,11 @@ namespace AIStudio.Wpf.Mind.Controls
{
_diagramViewModel.IsLoading = true;
_diagramViewModel.Items.Clear();
//_diagramViewModel.ToObject(json);
MindNode level1node = new MindNode(_diagramViewModel, Mind.NodeLevel.Level1, _diagramViewModel.MindType) { Text = "思维导图" };
_diagramViewModel.DirectAddItemCommand.Execute(level1node);
level1node.Left = 200;
level1node.Top = 200;
_diagramViewModel.DoCommandManager.Init();
_diagramViewModel.IsLoading = false;
}

View File

@@ -3,10 +3,18 @@
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:local="clr-namespace:AIStudio.Wpf.Mind.Controls"
xmlns:dd="https://gitee.com/akwkevin/aistudio.-wpf.-diagram"
xmlns:controls="clr-namespace:AIStudio.Wpf.Mind.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" >
<Grid Height="60">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/AIStudio.Wpf.Mind;component/Styles/Button.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid Height="70">
<TabControl>
<TabItem Header="思路">
<Grid>
@@ -14,6 +22,112 @@
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="0" Command="{Binding UndoCommand}">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M255.545 8c-66.269.119-126.438 26.233-170.86 68.685L48.971 40.971C33.851 25.851 8 36.559 8 57.941V192c0 13.255 10.745 24 24 24h134.059c21.382 0 32.09-25.851 16.971-40.971l-41.75-41.75c30.864-28.899 70.801-44.907 113.23-45.273 92.398-.798 170.283 73.977 169.484 169.442C423.236 348.009 349.816 424 256 424c-41.127 0-79.997-14.678-110.63-41.556-4.743-4.161-11.906-3.908-16.368.553L89.34 422.659c-4.872 4.872-4.631 12.815.482 17.433C133.798 479.813 192.074 504 256 504c136.966 0 247.999-111.033 248-247.998C504.001 119.193 392.354 7.755 255.545 8z"></Path>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="1" Grid.Column="0" Command="{Binding RedoCommand}">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M256.455 8c66.269.119 126.437 26.233 170.859 68.685l35.715-35.715C478.149 25.851 504 36.559 504 57.941V192c0 13.255-10.745 24-24 24H345.941c-21.382 0-32.09-25.851-16.971-40.971l41.75-41.75c-30.864-28.899-70.801-44.907-113.23-45.273-92.398-.798-170.283 73.977-169.484 169.442C88.764 348.009 162.184 424 256 424c41.127 0 79.997-14.678 110.629-41.556 4.743-4.161 11.906-3.908 16.368.553l39.662 39.662c4.872 4.872 4.631 12.815-.482 17.433C378.202 479.813 319.926 504 256 504 119.034 504 8.001 392.967 8 256.002 7.999 119.193 119.646 7.755 256.455 8z"></Path>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="1" Command="{Binding AddChildCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M992.9 500.1H355c-19.3 0-35 15.7-35 35V660H182V340.8h427.8c32 0 58-26 58-58V58c0-32-25.9-58-58-58H58C26 0 0 26 0 58v224.8c0 32 26 58 58 58h54V689c0 13.3 7.4 24.8 18.2 30.7 6.3 6.3 15.1 10.3 24.8 10.3h165v145.9c0 19.3 15.7 35 35 35h226c19.3 0 35-15.7 35-35s-15.7-35-35-35H390V570.1h567.9V611c0 19.3 15.7 35 35 35s35-15.7 35-35v-75.9c0-19.3-15.7-35-35-35zM70 70h527.8v200.8H70V70zM989 830h-89v-89c0-19.3-15.7-35-35-35s-35 15.7-35 35v89h-89c-19.3 0-35 15.7-35 35s15.7 35 35 35h89v89c0 19.3 15.7 35 35 35s35-15.7 35-35v-89h89c19.3 0 35-15.7 35-35s-15.7-35-35-35z"></Path>
<TextBlock>插入下级主题</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="1" Grid.Column="1" Command="{Binding AddPeerCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M651.8 775.5h-20.3v-527h178V305c0 19.3 15.7 35 35 35s35-15.7 35-35v-91.5c0-19.3-15.7-35-35-35h-248c-19.3 0-35 15.7-35 35V477H340.8V236.1c0-32-26-58-58-58H58c-32 0-58 26-58 58v551.8c0 32 26 58 58 58h224.8c32 0 58-26 58-58V547h220.7v263.5c0 19.3 15.7 35 35 35h55.3c19.3 0 35-15.7 35-35s-15.7-35-35-35z m-381 0.4H70V248.1h200.8v527.8zM990 651.5h-89v-89c0-19.3-15.7-35-35-35s-35 15.7-35 35v89h-89c-19.3 0-35 15.7-35 35s15.7 35 35 35h89v89c0 19.3 15.7 35 35 35s35-15.7 35-35v-89h89c19.3 0 35-15.7 35-35s-15.7-35-35-35z"></Path>
<TextBlock>插入同级主题</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="2" Command="{Binding AddParentCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" RenderTransformOrigin="0.5,0.5" Data="M992.9 500.1H355c-19.3 0-35 15.7-35 35V660H182V340.8h427.8c32 0 58-26 58-58V58c0-32-25.9-58-58-58H58C26 0 0 26 0 58v224.8c0 32 26 58 58 58h54V689c0 13.3 7.4 24.8 18.2 30.7 6.3 6.3 15.1 10.3 24.8 10.3h165v145.9c0 19.3 15.7 35 35 35h226c19.3 0 35-15.7 35-35s-15.7-35-35-35H390V570.1h567.9V611c0 19.3 15.7 35 35 35s35-15.7 35-35v-75.9c0-19.3-15.7-35-35-35zM70 70h527.8v200.8H70V70zM989 830h-89v-89c0-19.3-15.7-35-35-35s-35 15.7-35 35v89h-89c-19.3 0-35 15.7-35 35s15.7 35 35 35h89v89c0 19.3 15.7 35 35 35s35-15.7 35-35v-89h89c19.3 0 35-15.7 35-35s-15.7-35-35-35z">
<Path.RenderTransform>
<ScaleTransform ScaleX="-1" ScaleY="-1"/>
</Path.RenderTransform>
</Path>
<TextBlock>插入上级主题</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="3" Command="{Binding MoveForwardCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M62.5 500L312.5 500L312.5 937.5L687.5 937.5L687.5 500L937.5 500L500 62.5Z"></Path>
<TextBlock>上移</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="1" Grid.Column="3" Command="{Binding MoveBackCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M687.5 62.5L312.5 62.5L312.5 500L62.5 500L500 937.5L937.4 500L687.5 500Z"></Path>
<TextBlock>下移</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Row="0" Grid.Column="4" Command="{Binding EditCommand}">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M8,12H16V14H8V12M10,20H6V4H13V9H18V12.1L20,10.1V8L14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H10V20M8,18H12.1L13,17.1V16H8V18M20.2,13C20.3,13 20.5,13.1 20.6,13.2L21.9,14.5C22.1,14.7 22.1,15.1 21.9,15.3L20.9,16.3L18.8,14.2L19.8,13.2C19.9,13.1 20,13 20.2,13M20.2,16.9L14.1,23H12V20.9L18.1,14.8L20.2,16.9Z"></Path>
<TextBlock>编辑</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource FlatButtonStyle}" Grid.Column="4" Command="{Binding DeleteSelfCommand}" Height="22" Grid.RowSpan="2" VerticalAlignment="Bottom">
<StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Stretch="Uniform" Fill="Black" Data="M 25.3333,23.75L 50.6667,23.75C 51.5411,23.75 51.8541,27.3125 51.8541,27.3125L 24.1458,27.3125C 24.1458,27.3125 24.4589,23.75 25.3333,23.75 Z M 35.625,19.7917L 40.375,19.7917C 40.8122,19.7917 41.9583,20.9378 41.9583,21.375C 41.9583,21.8122 40.8122,22.9584 40.375,22.9584L 35.625,22.9584C 35.1878,22.9584 34.0416,21.8122 34.0416,21.375C 34.0416,20.9378 35.1878,19.7917 35.625,19.7917 Z M 27.7083,28.5L 48.2916,28.5C 49.1661,28.5 49.875,29.2089 49.875,30.0834L 48.2916,53.8334C 48.2916,54.7078 47.5828,55.4167 46.7083,55.4167L 29.2917,55.4167C 28.4172,55.4167 27.7083,54.7078 27.7083,53.8334L 26.125,30.0834C 26.125,29.2089 26.8339,28.5 27.7083,28.5 Z M 30.0833,31.6667L 30.4792,52.25L 33.25,52.25L 32.8542,31.6667L 30.0833,31.6667 Z M 36.4167,31.6667L 36.4167,52.25L 39.5833,52.25L 39.5833,31.6667L 36.4167,31.6667 Z M 43.1458,31.6667L 42.75,52.25L 45.5208,52.25L 45.9167,31.6667L 43.1458,31.6667 Z "></Path>
<TextBlock>删除</TextBlock>
</StackPanel>
</Button>
<controls:DropDownButton Grid.RowSpan="2" Grid.Column="5" >
<controls:DropDownButton.Content>
<StackPanel>
<Path Width="18" Height="18" Stretch="Uniform" Fill="Black" Data="M 23.4963,46.1288L 25.0796,48.8712L 29.4053,50.0303L 33.519,47.6553L 34.8902,46.8636L 37.6326,45.2803L 38.4242,46.6515L 37.2652,50.9772L 30.4091,54.9356L 21.7577,52.6174L 18.591,47.1326L 20.9091,38.4811L 27.7652,34.5227L 32.0909,35.6818L 32.8826,37.053L 30.1402,38.6364L 28.769,39.428L 24.6553,41.803L 23.4963,46.1288 Z M 38.7348,28.1895L 45.5908,24.2311L 54.2423,26.5493L 57.409,32.0341L 55.0908,40.6856L 48.2348,44.6439L 43.9091,43.4848L 43.1174,42.1136L 45.8598,40.5303L 47.231,39.7386L 51.3446,37.3636L 52.5037,33.0379L 50.9204,30.2955L 46.5946,29.1364L 42.481,31.5114L 41.1098,32.3031L 38.3674,33.8864L 37.5757,32.5152L 38.7348,28.1895 Z M 33.9006,45.1496L 31.7377,44.5701L 30.5502,42.5133L 31.1298,40.3504L 42.0994,34.0171L 44.2623,34.5966L 45.4498,36.6534L 44.8702,38.8163L 33.9006,45.1496 Z "></Path>
<TextBlock>链接</TextBlock>
</StackPanel>
</controls:DropDownButton.Content>
<controls:DropDownButton.Items>
<MenuItem Header="插入链接"></MenuItem>
<MenuItem Header="移除已有链接"></MenuItem>
</controls:DropDownButton.Items>
</controls:DropDownButton>
<controls:DropDownButton Grid.RowSpan="2" Grid.Column="6" >
<controls:DropDownButton.Content>
<StackPanel>
<Path Width="18" Height="18" Stretch="Uniform" Fill="Black" Data="M250 645L350 745L625 470L800 645L950 495V950H250V645zM250 503.55V250H405L554.3000000000001 399.25L350 603.55L250 503.55zM546.45 250H950V353.5500000000001L800 503.5500000000001L546.45 250zM200 1050H1000A50 50 0 0 0 1050 1000V200A50 50 0 0 0 1000 150H200A50 50 0 0 0 150 200V1000A50 50 0 0 0 200 1050zM775 700A75 75 0 1 0 775 850A75 75 0 0 0 775 700z"></Path>
<TextBlock>图片</TextBlock>
</StackPanel>
</controls:DropDownButton.Content>
<controls:DropDownButton.Items>
<MenuItem Header="插入图片"></MenuItem>
<MenuItem Header="移除已有图片"></MenuItem>
</controls:DropDownButton.Items>
</controls:DropDownButton>
<controls:DropDownButton Grid.RowSpan="2" Grid.Column="7" >
<controls:DropDownButton.Content>
<StackPanel>
<Path Width="18" Height="18" Stretch="Uniform" Fill="Black" Data="M5,3C3.89,3 3,3.89 3,5V19C3,20.11 3.89,21 5,21H19C20.11,21 21,20.11 21,19V5C21,3.89 20.11,3 19,3H5M5,5H19V19H5V5M7,7V9H17V7H7M7,11V13H17V11H7M7,15V17H14V15H7Z"></Path>
<TextBlock>备注</TextBlock>
</StackPanel>
</controls:DropDownButton.Content>
<controls:DropDownButton.Items>
<MenuItem Header="插入备注"></MenuItem>
<MenuItem Header="移除已有备注"></MenuItem>
</controls:DropDownButton.Items>
</controls:DropDownButton>
</Grid>
</TabItem>
<TabItem Header="外观">
@@ -22,6 +136,36 @@
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<controls:DropDownButton Grid.RowSpan="2" Grid.Column="7">
<controls:DropDownButton.Content>
<StackPanel>
<Path Width="18" Height="18" Stretch="Uniform" Fill="Black" Data="M5,3C3.89,3 3,3.89 3,5V19C3,20.11 3.89,21 5,21H19C20.11,21 21,20.11 21,19V5C21,3.89 20.11,3 19,3H5M5,5H19V19H5V5M7,7V9H17V7H7M7,11V13H17V11H7M7,15V17H14V15H7Z"></Path>
<TextBlock>类型</TextBlock>
</StackPanel>
</controls:DropDownButton.Content>
<controls:DropDownButton.Items>
<MenuItem Header="思维导图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Mind'}, ConverterParameter='Mind'}" />
<MenuItem Header="目录组织图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Directory'}, ConverterParameter='Directory'}" />
<MenuItem Header="鱼骨头图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='FishBone'}, ConverterParameter='FishBone'}" />
<MenuItem Header="逻辑结构图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Logical'}, ConverterParameter='Logical'}" />
<MenuItem Header="组织结构图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Organizational'}, ConverterParameter='Organizational'}" />
<MenuItem Header="天盘图" IsCheckable="True" IsChecked="{Binding MindType,Converter={dd:ConverterValueMapToBool Parameter='Celestial'}, ConverterParameter='Celestial'}" />
</controls:DropDownButton.Items>
</controls:DropDownButton>
</Grid>
</TabItem>
<TabItem Header="视图">