走进WPF之开发类似Visio软件
當(dāng)你想畫一個流程圖的時候,你會發(fā)現(xiàn),很多軟件要么需要秘鑰,要么需要會員,這時我就在想,可不可自己制作一款流程圖軟件呢?本文以一個簡單的小例子,簡述如何利用WPF制作屬于自己的流程圖軟件,僅供學(xué)習(xí)分享使用,如有不足之處,還請指正。
涉及知識點
本示例主要通過WPF技術(shù)進行開發(fā),涉及知識點如下:
Thumb控件簡介
Thumb控件是WPF提供的用于用戶拖動的控件。默認(rèn)情況下,Thumb控件并不在工具箱中,需要手動添加,如下所示:
工具箱-->常規(guī)-->右鍵-->選擇項,然后打開【選擇工具箱對話框】,如下所示:
在選【擇工具箱項】頁面,打開WPF組件-->選擇Thumb-->點擊確定按鈕,如下所示:
?添加成功后,即可從工具箱拖動到頁面,如下所示:
關(guān)于Thumb控件的簡介,如下所示:
namespace System.Windows.Controls.Primitives {//// 摘要:// 表示可以由用戶拖動的控件。[DefaultEvent("DragDelta")][Localizability(LocalizationCategory.NeverLocalize)]public class Thumb : Control{//// 摘要:// 標(biāo)識 System.Windows.Controls.Primitives.Thumb.DragStarted 路由事件。//// 返回結(jié)果:// System.Windows.Controls.Primitives.Thumb.DragStarted 路由事件的標(biāo)識符。public static readonly RoutedEvent DragStartedEvent;//// 摘要:// 標(biāo)識 System.Windows.Controls.Primitives.Thumb.DragDelta 路由事件。//// 返回結(jié)果:// System.Windows.Controls.Primitives.Thumb.DragDelta 路由事件的標(biāo)識符。public static readonly RoutedEvent DragDeltaEvent;//// 摘要:// 標(biāo)識 System.Windows.Controls.Primitives.Thumb.DragCompleted 路由事件。//// 返回結(jié)果:// System.Windows.Controls.Primitives.Thumb.DragCompleted 路由事件的標(biāo)識符。public static readonly RoutedEvent DragCompletedEvent;//// 摘要:// 標(biāo)識 System.Windows.Controls.Primitives.Thumb.IsDragging 依賴屬性。//// 返回結(jié)果:// System.Windows.Controls.Primitives.Thumb.IsDragging 依賴項屬性的標(biāo)識符。public static readonly DependencyProperty IsDraggingProperty;//// 摘要:// 初始化 System.Windows.Controls.Primitives.Thumb 類的新實例。public Thumb();//// 摘要:// 獲取是否 System.Windows.Controls.Primitives.Thumb 控件具有邏輯焦點和捕獲鼠標(biāo)并按下鼠標(biāo)左鍵。//// 返回結(jié)果:// true 如果 System.Windows.Controls.Primitives.Thumb 控件具有焦點且鼠標(biāo)捕獲; 否則為 false。 默認(rèn)值為// false。[Bindable(true)][Browsable(false)][Category("Appearance")]public bool IsDragging { get; protected set; }//// 摘要:// 發(fā)生時 System.Windows.Controls.Primitives.Thumb 控件接收邏輯焦點和鼠標(biāo)捕獲。[Category("Behavior")]public event DragStartedEventHandler DragStarted;//// 摘要:// 根據(jù)鼠標(biāo)位置更改時出現(xiàn)了一個或多個次 System.Windows.Controls.Primitives.Thumb 控件具有邏輯焦點和鼠標(biāo)捕獲。[Category("Behavior")]public event DragDeltaEventHandler DragDelta;//// 摘要:// 發(fā)生時 System.Windows.Controls.Primitives.Thumb 控件失去鼠標(biāo)捕獲。[Category("Behavior")]public event DragCompletedEventHandler DragCompleted;//// 摘要:// 取消的拖動操作 System.Windows.Controls.Primitives.Thumb。public void CancelDrag();//// 摘要:// 創(chuàng)建 System.Windows.Automation.Peers.AutomationPeer 為 System.Windows.Controls.Primitives.Thumb// 控件。//// 返回結(jié)果:// 一個 System.Windows.Automation.Peers.ThumbAutomationPeer 為 System.Windows.Controls.Primitives.Thumb// 控件。protected override AutomationPeer OnCreateAutomationPeer();//// 摘要:// 響應(yīng) System.Windows.Controls.Primitives.Thumb.IsDragging 屬性值的更改。//// 參數(shù):// e:// 事件數(shù)據(jù)。protected virtual void OnDraggingChanged(DependencyPropertyChangedEventArgs e);//// 摘要:// 提供類處理 System.Windows.ContentElement.MouseLeftButtonDown 事件。//// 參數(shù):// e:// 事件數(shù)據(jù)。protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e);//// 摘要:// 提供類處理 System.Windows.ContentElement.MouseLeftButtonUp 事件。//// 參數(shù):// e:// 事件數(shù)據(jù)。protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e);//// 摘要:// 提供類處理 System.Windows.UIElement.MouseMove 事件。//// 參數(shù):// e:// 事件數(shù)據(jù)。protected override void OnMouseMove(MouseEventArgs e);} }通過上述摘要簡介,發(fā)現(xiàn)Thumb控件提供了三個事件,分別是:
- 拖動開始事件:public event DragStartedEventHandler DragStarted;
- 拖動進行事件:public event DragDeltaEventHandler DragDelta;
- 拖動完成事件:public event DragCompletedEventHandler DragCompleted;
?Thumb控件示例
首先在窗口頁面上添加一個Thumb控件,然后分別添加三個事件,如下所示:
<Window x:Class="DemoVisio.MainWindow1"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:DemoVisio"mc:Ignorable="d"Title="Thumb示例" Height="450" Width="800"><Canvas><Thumb x:Name="thumb" Canvas.Left="0" Canvas.Top="0" Height="100" Width="100" DragStarted="thumb_DragStarted" DragDelta="thumb_DragDelta" DragCompleted="thumb_DragCompleted"/></Canvas> </Window>然后在三個事件中添加代碼,終點是DragDelta事件,如下所示:
namespace DemoVisio {/// <summary>/// MainWindow1.xaml 的交互邏輯/// </summary>public partial class MainWindow1 : Window{public MainWindow1(){InitializeComponent();}private void thumb_DragStarted(object sender, DragStartedEventArgs e){//開始拖動}/// <summary>/// 拖動/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e){Thumb myThumb = (Thumb)sender;double nTop = Canvas.GetTop(myThumb) + e.VerticalChange;double nLeft = Canvas.GetLeft(myThumb) + e.HorizontalChange;Canvas.SetTop(myThumb, nTop);Canvas.SetLeft(myThumb, nLeft);}private void thumb_DragCompleted(object sender, DragCompletedEventArgs e){//拖動完成}} }注意,在XAML中,Thumb一定是在Canvas布局容器中,且一定要設(shè)置【Canvas.Left="0" Canvas.Top="0"】兩個屬性,如果不設(shè)置,在值為NaN,無法進行拖動。
默認(rèn)情況下,Thumb控件就是一個丑丑的方塊,如下所示:
拖動控件基類
在本示例中,流程圖需要多種控件(如:圓形,矩形,線等),不能每一個控件都去實現(xiàn)那三個事件【DragStarted,DragDelta,DragCompleted】,所以需要定義一個基類ThumbControl,統(tǒng)一實現(xiàn)方案。具體如下所示:
namespace DemoVisio {public class ThumbControl : Thumb{/// <summary>/// 是否可以輸入/// </summary>public bool IsEnableInput { get { return (bool)GetValue(IsEnableInputProperty); } set {SetValue( IsEnableInputProperty, value); } }/// <summary>/// 依賴屬性/// </summary>public static readonly DependencyProperty IsEnableInputProperty = DependencyProperty.Register("IsEnableInput",typeof(bool),typeof(ThumbControl));public ThumbControl():base() {this.DragStarted += ThumbControl_DragStarted;this.DragDelta += ThumbControl_DragDelta;this.DragCompleted += ThumbControl_DragCompleted;this.MouseDoubleClick += ThumbControl_MouseDoubleClick;this.IsKeyboardFocusedChanged += ThumbControl_IsKeyboardFocusedChanged;}public void SetIsEnableInput(bool flag){this.IsEnableInput = flag;}/// <summary>/// 是否具有鍵盤焦點/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void ThumbControl_IsKeyboardFocusedChanged(object sender, DependencyPropertyChangedEventArgs e){this.IsEnableInput = this.IsKeyboardFocused;}/// <summary>/// 雙擊事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void ThumbControl_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e){this.IsEnableInput = true;}private void ThumbControl_DragStarted(object sender, DragStartedEventArgs e){//開始移動}private void ThumbControl_DragDelta(object sender, DragDeltaEventArgs e){Thumb myThumb = (Thumb)sender;double nTop = Canvas.GetTop(myThumb) + e.VerticalChange;double nLeft = Canvas.GetLeft(myThumb) + e.HorizontalChange;Canvas.SetTop(myThumb, nTop);Canvas.SetLeft(myThumb, nLeft);}private void ThumbControl_DragCompleted(object sender, DragCompletedEventArgs e){//移動結(jié)束}} }具體圖形控件
封裝了基類以后,其他控件可以在此基礎(chǔ)上進行使用,通過ControlTemplate展現(xiàn)不同的形態(tài),如下所示:
1. 矩形方塊
在流程圖中,矩形方塊一般表示過程,實現(xiàn)代碼如下所示:
<UserControl x:Class="DemoVisio.SquareControl"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:local="clr-namespace:DemoVisio"mc:Ignorable="d"d:DesignHeight="450" d:DesignWidth="800"><Canvas><local:ThumbControl x:Name="s" BorderThickness="1" Canvas.Top ="0" Canvas.Left="0" Width="100" Height="60" Background="AliceBlue"><Thumb.Template><ControlTemplate><Border Width="{Binding ElementName=s, Path=Width}" Height="{Binding ElementName=s, Path=Height}" BorderBrush="Black" Background="{Binding ElementName=s, Path=Background}" BorderThickness="{Binding ElementName=s, Path=BorderThickness}" Padding="2"><TextBox Background="{Binding ElementName=s, Path=Background}" BorderThickness="0" VerticalAlignment="Center" IsEnabled="{Binding ElementName=s, Path=IsEnableInput}" MinLines="3" MaxLines="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"></TextBox></Border></ControlTemplate></Thumb.Template></local:ThumbControl></Canvas> </UserControl>2. 圓形圖
在流程圖中,圓形一般表示開始和結(jié)束,如下所示:
<UserControl x:Class="DemoVisio.CircleControl"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:local="clr-namespace:DemoVisio"mc:Ignorable="d"d:DesignHeight="450" d:DesignWidth="800"><Canvas><local:ThumbControl x:Name="s" Canvas.Top ="0" Canvas.Left="0" Width="60" Height="60" Background="AliceBlue" BorderThickness="1" ><local:ThumbControl.Template><ControlTemplate><Grid><Border Width="{Binding Width}" Height="{Binding Height}" CornerRadius="30" BorderThickness="{Binding ElementName=s, Path=BorderThickness}" BorderBrush="Black" Background="{Binding ElementName=s, Path=Background}"><TextBox VerticalAlignment="Center" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" MaxLines="2" MinLines="1" Width="{Binding Width}" Height="{Binding Height}" Background="{Binding ElementName=s, Path=Background}" BorderThickness="0" IsEnabled="{Binding ElementName=s, Path=IsEnableInput}"></TextBox></Border></Grid></ControlTemplate></local:ThumbControl.Template></local:ThumbControl></Canvas> </UserControl>3. 菱形圖
在流程圖中,菱形一般表示選擇,表達(dá)程序中的布爾值。如下所示:
<UserControl x:Class="DemoVisio.RhombusControl"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:local="clr-namespace:DemoVisio"mc:Ignorable="d"d:DesignHeight="450" d:DesignWidth="800"><Canvas><local:ThumbControl x:Name="s" Canvas.Left="0" Canvas.Top="0"? Width="80" Height="80" Background="AliceBlue" BorderThickness="1" ><Thumb.Template><ControlTemplate><Border Width="{Binding ElementName=s, Path=Width}" Height="{Binding ElementName=s, Path=Height}" BorderBrush="Black" Background="{Binding ElementName=s, Path=Background}" BorderThickness="{Binding ElementName=s, Path=BorderThickness}" Padding="1"><TextBox Background="{Binding ElementName=s, Path=Background}" BorderThickness="0" VerticalAlignment="Center" IsEnabled="{Binding ElementName=s, Path=IsEnableInput}" Width="50" Height="50" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"><TextBox.RenderTransform><RotateTransform CenterX="25" CenterY="25" Angle="-45" ></RotateTransform></TextBox.RenderTransform></TextBox></Border></ControlTemplate></Thumb.Template><Thumb.RenderTransform><TransformGroup><RotateTransform CenterX="40" CenterY="40" Angle="45"></RotateTransform><ScaleTransform CenterX="40" CenterY="40" ScaleX="0.8"></ScaleTransform><TranslateTransform X="10" Y="15"></TranslateTransform></TransformGroup></Thumb.RenderTransform></local:ThumbControl></Canvas> </UserControl>4. 直線
在流程圖中,直線一般表示兩個過程之間的連接,如下所示:
<UserControl x:Class="DemoVisio.LineArrowControl"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:local="clr-namespace:DemoVisio"mc:Ignorable="d"d:DesignHeight="450" d:DesignWidth="800"><Canvas><local:ThumbControl x:Name="s" Canvas.Left="0" Canvas.Top="0"? Width="100" Height="100" Background="AliceBlue" IsEnableInput="False"><local:ThumbControl.Template><ControlTemplate><Grid><Line X1="0" Y1="0" X2="0" Y2="100" Stroke="Black" StrokeThickness="2" HorizontalAlignment="Center" ></Line><Line X1="-5" Y1="90" X2="1" Y2="100" StrokeThickness="2" Stroke="Black" HorizontalAlignment="Center"></Line><Line X1="8" Y1="90" X2="3" Y2="100" StrokeThickness="2" Stroke="Black" HorizontalAlignment="Center"></Line><TextBox VerticalAlignment="Center" Height="30" HorizontalContentAlignment="Center" BorderThickness="0" VerticalContentAlignment="Center" MinLines="1" MaxLines="2" IsEnabled="{Binding ElementName=s, Path=IsEnableInput}" Opacity="0" Visibility="{Binding ElementName=s, Path=IsEnableInput}"></TextBox></Grid></ControlTemplate></local:ThumbControl.Template></local:ThumbControl></Canvas> </UserControl>主窗體
主窗體主要用于繪制流程圖,分為左右兩部分,左邊是控件列表,右邊是布局容器,如下所示:
<Window x:Class="DemoVisio.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:DemoVisio"mc:Ignorable="d"Title="流程圖" Height="800" Width="800" MouseDown="Window_MouseDown" Loaded="Window_Loaded"><Window.Resources><Style TargetType="TextBlock"><Setter Property="HorizontalAlignment" Value="Center"></Setter></Style></Window.Resources><Grid ShowGridLines="True"><Grid.ColumnDefinitions><ColumnDefinition Width="Auto" MinWidth="150"></ColumnDefinition><ColumnDefinition Width="*"></ColumnDefinition></Grid.ColumnDefinitions><StackPanel Grid.Column="0" x:Name="left" Orientation="Vertical"><Rectangle Width="80" Height="50" Fill="AliceBlue" Stroke="Black" Margin="5" x:Name="rectangle" MouseLeftButtonDown="rectangle_MouseLeftButtonDown"></Rectangle><TextBlock Text="矩形"></TextBlock><Rectangle Width="100" Height="100" Fill="AliceBlue" Stroke="Black" Margin="5" x:Name="rhombus" MouseLeftButtonDown="rhombus_MouseLeftButtonDown"><Rectangle.RenderTransform><TransformGroup><RotateTransform CenterX="50" CenterY="50" Angle="45"></RotateTransform><ScaleTransform CenterX="50" CenterY="50" ScaleX="0.5" ScaleY="0.7"></ScaleTransform></TransformGroup></Rectangle.RenderTransform></Rectangle><TextBlock Text="菱形" Margin="0,5"></TextBlock><Line X1="0" Y1="0" X2="0" Y2="80" Stroke="Black" StrokeThickness="2" HorizontalAlignment="Center" Margin="5" x:Name="line" MouseLeftButtonDown="line_MouseLeftButtonDown" ></Line><TextBlock Text="直線"></TextBlock><Ellipse Width="60" Height="60" Fill="AliceBlue" Stroke="Black" Margin="5" x:Name="circle" MouseLeftButtonDown="circle_MouseLeftButtonDown"></Ellipse><TextBlock Text="圓形"></TextBlock></StackPanel><Canvas Grid.Column="1" x:Name="right" ></Canvas></Grid> </Window>當(dāng)點擊左邊基礎(chǔ)控件時,在右邊容器中,生成新的控件。如下所示:
namespace DemoVisio {/// <summary>/// MainWindow.xaml 的交互邏輯/// </summary>public partial class MainWindow : Window{/// <summary>/// 控件列表/// </summary>private List<Control> rightControls = new List<Control>();public MainWindow(){InitializeComponent();}private void Window_MouseDown(object sender, MouseButtonEventArgs e){//this.Focus();//this.one.SetIsEnableInput(false);foreach (var control in this.right.Children) {var thumb = control as ThumbControl;if (thumb != null){thumb.SetIsEnableInput(false);}}}private void Window_Loaded(object sender, RoutedEventArgs e){var width = this.right.ActualWidth;var height = this.right.ActualHeight;int x = 0;int y = 0;//橫線while (y<height) {Line line = new Line();line.X1 = x;line.Y1 = y;line.X2 = width;line.Y2 = y;line.Stroke = Brushes.LightGray;line.StrokeThickness = 1;this.right.Children.Add(line);y = y + 10;}//重新初始化值x = 0;y = 0;//豎線while (x < width) {Line line = new Line();line.X1 = x;line.Y1 = y;line.X2 = x;line.Y2 = height;line.Stroke = Brushes.LightGray;line.StrokeThickness = 1;this.right.Children.Add(line);x = x + 10;}}private void rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){SquareControl squareControl = new SquareControl();this.right.Children.Add(squareControl);}private void rhombus_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){RhombusControl rhombusControl = new RhombusControl();this.right.Children.Add(rhombusControl);}private void line_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){LineArrowControl lineArrowControl = new LineArrowControl();this.right.Children.Add(lineArrowControl);}private void circle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){CircleControl circleControl = new CircleControl();this.right.Children.Add(circleControl);}} }示例截圖
示例基礎(chǔ)截圖如下所示:
備注
以上示例只是基礎(chǔ),功能并不完善,旨在拋磚引玉,共同學(xué)習(xí),一起進步,希望可以對大家有所啟發(fā)。
賀新郎·九日
【作者】劉克莊?【朝代】宋
湛湛長空黑。更那堪、斜風(fēng)細(xì)雨,亂愁如織。
老眼平生空四海,賴有高樓百尺。
看浩蕩、千崖秋色。
白發(fā)書生神州淚,盡凄涼、不向牛山滴。
追往事,去無跡。
少年自負(fù)凌云筆。到而今、春華落盡,滿懷蕭瑟。
常恨世人新意少,愛說南朝狂客。
把破帽、年年拈出。
若對黃花孤負(fù)酒,怕黃花、也笑人岑寂。
鴻北去,日西匿。
總結(jié)
以上是生活随笔為你收集整理的走进WPF之开发类似Visio软件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js字符串转数字(小数),数字转字符串
- 下一篇: Microsoft Edge 浏览器如何