WPF——效果和可视化对象

界面设计






添加

删除


选择移动



选择多个





csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp2
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        //选择移动
        private bool isDragging = false;
        private Vector vectorOffset = new Vector();
        private DrawingVisual selectVisual;
        //多选
        private bool isMultSelect = false;
        private DrawingVisual selectionSquare;
        private Point selectionSquareTopLeft;
        private void drawingSurface_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Point point = e.GetPosition(drawingSurface);
            if (cmdAdd.IsChecked==true)
            {
                
                DrawingVisual visual = new DrawingVisual();
                this.DrawSquare(visual,point,false);
                drawingSurface.AddVisual(visual);
            }
            if (cmdMove.IsChecked == true)
            {
                DrawingVisual visual = drawingSurface.GetVisual(point);
                if (visual != null)
                {
                    isDragging = true;
                    Point topLeftPoint = new Point();
                    topLeftPoint.X = visual.ContentBounds.TopLeft.X + drawingPen.Thickness / 2;
                    topLeftPoint.Y = visual.ContentBounds.TopLeft.Y + drawingPen.Thickness / 2;
                    vectorOffset = topLeftPoint - point;
                    DrawSquare(visual, topLeftPoint,true);
                    if (selectVisual != null && visual != selectVisual)
                    {
                        ClearSelection();
                    }
                    selectVisual = visual;
                }

            }
            if (cmdDelete.IsChecked == true)
            {
                DrawingVisual visual= drawingSurface.GetVisual(point);
                if (visual != null)
                    drawingSurface.Delete(visual);
            }
            if (cmdMultSelect.IsChecked == true)
            {
                isMultSelect = true;
                selectionSquare = new DrawingVisual();
                drawingSurface.AddVisual(selectionSquare);
                selectionSquareTopLeft = e.GetPosition(drawingSurface);
                Mouse.Capture(drawingSurface);
            }
        }
        private Brush drawingBrush = Brushes.AliceBlue;
        private Pen drawingPen= new Pen(Brushes.SteelBlue,3);
        private Size drawSize = new Size(30,30);
        private Brush selectDrawingBrush = Brushes.Yellow;
        private void DrawSquare(DrawingVisual visual, Point point, bool v)
        {
            using (DrawingContext dt = visual.RenderOpen())
            {
                Brush brush = drawingBrush;
                if (v)
                {
                    brush = selectDrawingBrush;
                }
                dt.DrawRectangle(brush, drawingPen,new Rect(point,drawSize));
            }
        }
        private void ClearSelection()
        {
            Point topLeftPoint = new Point();
            topLeftPoint.X = selectVisual.ContentBounds.TopLeft.X + drawingPen.Thickness / 2;
            topLeftPoint.Y = selectVisual.ContentBounds.TopLeft.Y + drawingPen.Thickness / 2;
            DrawSquare(selectVisual, topLeftPoint,false);
            selectVisual = null;
        }
        private Brush selectionSquareBrush = Brushes.Transparent;
        private Pen selectionSquarePen = new Pen(Brushes.Black,2);
        private void DrawSelectionSquare(Point point1,Point point2)
        {
            selectionSquarePen.DashStyle = DashStyles.Dash;
            using (DrawingContext dt = selectionSquare.RenderOpen())
            {
                dt.DrawRectangle(selectionSquareBrush,selectionSquarePen,new Rect(point1,point2));
            }
        }
        private void drawingSurface_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (isDragging)
            {
                isDragging = false;
            }
            if (isMultSelect)
            {
                isMultSelect = false;
                Rect rect = new Rect(selectionSquareTopLeft,e.GetPosition(drawingSurface));
                RectangleGeometry rectangleGeometry = new RectangleGeometry(rect);
                List<DrawingVisual> drawingVisuals = drawingSurface.GetVisuals(rectangleGeometry);
                MessageBox.Show($"选择了{drawingVisuals.Count}个方格");
                drawingSurface.Delete(selectionSquare);
                Mouse.Capture(null);
            }
        }
        private void drawingSurface_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                Point point = e.GetPosition(drawingSurface) + vectorOffset;
                DrawSquare(selectVisual, point, true);
            }
            if (isMultSelect)
            {
                Point point = e.GetPosition(drawingSurface);
                DrawSelectionSquare(selectionSquareTopLeft, point);
            }
        }
    }
}
csharp 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace WpfApp2
{
    public class DrawingCanvas:Canvas
    {
        private List<Visual> visuals = new List<Visual>();


        protected override int VisualChildrenCount
        {
            get
            {
                return visuals.Count;
            }
        }

        protected override Visual GetVisualChild(int index)
        {
            if (index < visuals.Count)
            {
                return visuals[index];
            }
            else
                return null;
        }
        public void AddVisual(Visual visual)
        {
            visuals.Add(visual);
            base.AddLogicalChild(visual);
            base.AddVisualChild(visual);
        }
        public DrawingVisual GetVisual(Point point)
        {
            HitTestResult hitTestResult = VisualTreeHelper.HitTest(this,point);
            return hitTestResult.VisualHit as DrawingVisual;
        }
        public void Delete(Visual visual)
        {
            visuals.Remove(visual);
            base.RemoveLogicalChild(visual);
            base.RemoveVisualChild(visual);
        }
        List<DrawingVisual> hits = new List<DrawingVisual>(); 
        public List<DrawingVisual> GetVisuals(Geometry geometry)
        {
            hits.Clear();
            HitTestResultCallback hitTestResultCallback = new HitTestResultCallback(hitResultFunc);
            GeometryHitTestParameters hitTestParameters = new GeometryHitTestParameters(geometry);
            VisualTreeHelper.HitTest(this,null, hitTestResultCallback, hitTestParameters);
            return hits;
           
        }

        private HitTestResultBehavior hitResultFunc(HitTestResult result)
        {
            GeometryHitTestResult geometry = (GeometryHitTestResult)result;
            DrawingVisual drawingVisual = result.VisualHit as DrawingVisual;
            if (drawingVisual != null && geometry.IntersectionDetail == IntersectionDetail.FullyInside)
            {
                hits.Add(drawingVisual);
            }
            return HitTestResultBehavior.Continue;
        }
    }
}
csharp 复制代码
<Window x:Class="WpfApp2.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:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ToolBarTray Orientation="Vertical">
            <ToolBar>
                <RadioButton Margin="0,3" IsChecked="true" Name="cmdAdd">
                    <StackPanel>
                        <Rectangle Width="30" Height="30" Stroke="SteelBlue" StrokeThickness="3" Fill="AliceBlue"/>
                        <TextBlock Text="添加"/>
                    </StackPanel>
                </RadioButton>
                <RadioButton Margin="0,3" IsChecked="true" Name="cmdMove">
                    <StackPanel>
                        <Rectangle Width="30" Height="30" Stroke="SteelBlue" StrokeThickness="3" Fill="AliceBlue"/>
                        <TextBlock Text="选择/移动"/>
                    </StackPanel>
                </RadioButton>
                <RadioButton Margin="0,3" IsChecked="true" Name="cmdDelete">
                    <StackPanel>
                        <Path Stroke="SteelBlue" StrokeThickness="3" StrokeEndLineCap="Round" StrokeStartLineCap="Round" Fill="Red" HorizontalAlignment="Center">
                            <Path.Data>
                                <GeometryGroup>
                                    <PathGeometry>
                                        <PathFigure StartPoint="0,0">
                                            <LineSegment Point="18,18"/>
                                        </PathFigure>
                                        <PathFigure StartPoint="18,0">
                                            <LineSegment Point="0,18"/>
                                        </PathFigure>
                                    </PathGeometry>
                                </GeometryGroup>
                            </Path.Data>
                        </Path>
                        <TextBlock Text="删除"/>
                    </StackPanel>
                </RadioButton>
                <RadioButton Margin="0,3" IsChecked="true" Name="cmdMultSelect">
                    <StackPanel>
                        <Rectangle Width="30" Height="30" Stroke="SteelBlue" StrokeThickness="3" Fill="AliceBlue"/>
                        <TextBlock Text="选择多个"/>
                    </StackPanel>
                </RadioButton>
            </ToolBar>
        </ToolBarTray>
        <Border Grid.Column="1" Margin="3" BorderBrush="SteelBlue" BorderThickness="1">
            <local:DrawingCanvas Background="Wheat" x:Name="drawingSurface" 
                                 MouseLeftButtonDown="drawingSurface_MouseLeftButtonDown"
                                 MouseMove="drawingSurface_MouseMove"
                                 MouseLeftButtonUp="drawingSurface_MouseLeftButtonUp"/>
        </Border>
    </Grid>
</Window>
相关推荐
加号312 小时前
【WPF】自定义颜色拾取器
wpf·自定义颜色拾取器
张人玉12 小时前
WPF 常用样式属性及示例笔记
笔记·wpf
张人玉14 小时前
WPF布局控件(界面骨架核心)
开发语言·c#·wpf·布局控件
亦陈不染17 小时前
c#入门详解(刘铁锰)06 - 数据持久化:TXT文本保存、序列化与反序列化(附详细源码)
开发语言·计算机视觉·c#·wpf
应用市场20 小时前
楼灯光矩阵显示系统:从理论到实践的完整技术方案
线性代数·矩阵·wpf
虚行1 天前
WPF入门
开发语言·c#·wpf
周杰伦fans1 天前
MahApps.Metro WPF 开发使用过程中遇到的问题 - 未能加载文件或程序集“Microsoft.Xaml.Behaviors,
microsoft·wpf
△曉風殘月〆1 天前
WPF中的坐标转换
wpf
一个天蝎座 白勺 程序猿2 天前
深度解析:通过ADO.NET驱动Kdbndp高效连接与操作Kingbase数据库
数据库·.net·wpf·kingbase·金仓数据库
时光追逐者2 天前
一个使用 WPF 开发的 Diagram 画板工具(包含流程图FlowChart,思维导图MindEditor)
c#·.net·wpf·流程图