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>
相关推荐
He BianGu5 小时前
【笔记】在WPF中Decorator是什么以及何时优先考虑 Decorator 派生类
笔记·wpf
时光追逐者18 小时前
一款专门为 WPF 打造的开源 Office 风格用户界面控件库
ui·开源·c#·.net·wpf
He BianGu18 小时前
【笔记】介绍 WPF XAML 中 Binding 的 StringFormat详细功能
笔记·wpf
Rotion_深2 天前
C# WPF使用线程池运行Action方法
c#·wpf·线程池
攻城狮CSU2 天前
WPF 深入系列.2.布局系统.尺寸属性
wpf
攻城狮CSU2 天前
WPF 深入系列.2.布局系统.布局控件.Grid
wpf
玖笙&2 天前
✨WPF编程基础【1.3】:XAML 名称空间
c++·wpf·visual studio
玖笙&2 天前
✨WPF编程基础【1.4】:类型转换器(含示例及源码)
c++·wpf·visual studio
Dream achiever4 天前
3.WPF - 依赖属性
c#·wpf