效果图

项目中需要做一个机台的平面视图,点击其中一个料盒时,弹出该料盒的料管列表,用WPF示例做了一下,效果如下:

用户控件XAML

 1 <UserControl x:Class="WpfApp1.Views.BoardStackControl"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6 xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
7 xmlns:local="clr-namespace:WpfApp1.Views"
8 xmlns:wpfapp1="clr-namespace:WpfApp1"
9 d:DataContext="{d:DesignInstance Type=wpfapp1:MainViewModel}"
10 Width="224" Height="300"
11 mc:Ignorable="d"
12 d:DesignHeight="300" d:DesignWidth="250">
13 <UserControl.DataContext>
14 <wpfapp1:MainViewModel />
15 </UserControl.DataContext>
16 <Grid>
17 <!--<ItemsControl ItemsSource="{Binding NestGroups}">
18 <ItemsControl.ItemsPanel>
19 <ItemsPanelTemplate>
20 <StackPanel Orientation="Horizontal"></StackPanel>
21 </ItemsPanelTemplate>
22 </ItemsControl.ItemsPanel>
23 <ItemsControl.ItemTemplate>
24 <DataTemplate>-->
25 <Border Margin="1">
26 <Grid Width="220" Height="220">
27 <Ellipse Stroke="#dcdfe3" StrokeThickness="3" Width="220" Height="220"/>
28 <Ellipse Stroke="#dcdfe3" StrokeThickness="3" Width="80" Height="80" HorizontalAlignment="Center" VerticalAlignment="Center"/>
29 <ItemsControl ItemsSource="{Binding LeftTubes3}">
30 <ItemsControl.ItemsPanel>
31 <ItemsPanelTemplate>
32 <Canvas/>
33 </ItemsPanelTemplate>
34 </ItemsControl.ItemsPanel>
35 <ItemsControl.ItemContainerStyle>
36 <Style TargetType="ContentPresenter">
37 <Setter Property="Canvas.Left" Value="{Binding X, Mode=OneWay}"/>
38 <Setter Property="Canvas.Top" Value="{Binding Y, Mode=OneWay}"/>
39 <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
40 <Setter Property="RenderTransform">
41 <Setter.Value>
42 <RotateTransform Angle="{Binding Angle}"/>
43 </Setter.Value>
44 </Setter>
45 </Style>
46 </ItemsControl.ItemContainerStyle>
47 <ItemsControl.ItemTemplate>
48 <DataTemplate>
49 <Grid>
50 <Border Width="35" Height="50" Tag="{Binding .}" x:Name="animatedBorder" MouseLeftButtonDown="Border_MouseLeftButtonDown"
51 CornerRadius="3" Background="#FFE6E6E6" BorderBrush="Gray" BorderThickness="1">
52 <ItemsControl ItemsSource="{Binding Tubes}" Margin="2" IsHitTestVisible="False">
53 <ItemsControl.ItemsPanel>
54 <ItemsPanelTemplate>
55 <UniformGrid Columns="{Binding Rows}" Rows="{Binding Cols}" IsHitTestVisible="False"/>
56 </ItemsPanelTemplate>
57 </ItemsControl.ItemsPanel>
58 <ItemsControl.ItemTemplate>
59 <DataTemplate>
60 <Ellipse Width="{Binding Width}" Height="{Binding Height}" Fill="#FF4F81BD" Margin="{Binding Margin}" Stroke="Black" StrokeThickness="0.5" IsHitTestVisible="False"/>
61 </DataTemplate>
62 </ItemsControl.ItemTemplate>
63 </ItemsControl>
64 <Border.Triggers>
65 <EventTrigger RoutedEvent="MouseLeftButtonUp">
66 <BeginStoryboard>
67 <Storyboard>
68 <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0.5" Duration="0:0:0.1" AutoReverse="True"/>
69 </Storyboard>
70 </BeginStoryboard>
71 </EventTrigger>
72 </Border.Triggers>
73 </Border>
74 <Border Width="20" Height="20" CornerRadius="10" Background="#FF4F81BD" BorderBrush="White" BorderThickness="1" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,-10,0,0">
75 <TextBlock Text="{Binding Index}" Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
76 </Border>
77 </Grid>
78 </DataTemplate>
79 </ItemsControl.ItemTemplate>
80 </ItemsControl>
81 </Grid>
82 </Border>
83 <!--</DataTemplate>
84 </ItemsControl.ItemTemplate>
85 </ItemsControl>-->
86
87 </Grid>
88 </UserControl>
89
90

用户控件XMAL.CS

 1 using CommunityToolkit.Mvvm.Messaging;
2 using Microsoft.Extensions.Logging;
3 using System.Collections.ObjectModel;
4 using System.Diagnostics;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Input;
8 using System.Windows.Media;
9 using WpfApp1.Entities;
10
11 namespace WpfApp1.Views;
12
13 public partial class BoardStackControl : UserControl
14 {
15 public BoardStackControl()
16 {
17 InitializeComponent();
18
19 }
20
21 public static readonly RoutedEvent BorderClickedEvent =
22 EventManager.RegisterRoutedEvent(
23 "BorderClicked",
24 RoutingStrategy.Bubble,
25 typeof(RoutedEventHandler),
26 typeof(BoardStackControl)
27 );
28
29 public event RoutedEventHandler BorderClicked
30 {
31 add => AddHandler(BorderClickedEvent, value);
32 remove => RemoveHandler(BorderClickedEvent, value);
33 }
34
35 private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
36 {
37 if (sender is Border border && border.DataContext is BoxPosition boxPosition)
38 {
39 // 触发路由事件,并携带索引
40 var args = new RoutedEventArgs(BorderClickedEvent, boxPosition.Index);
41 RaiseEvent(args);
42 e.Handled = true;
43 }
44 }
45
46 }

主窗口XAML

 1 <Window x:Class="WpfApp1.MainWindow"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6 xmlns:local="clr-namespace:WpfApp1"
7 xmlns:view="clr-namespace:WpfApp1.Views"
8 mc:Ignorable="d"
9 Title="MainWindow" Height="450" Width="800">
10 <Window.DataContext>
11 <local:MainViewModel />
12 </Window.DataContext>
13 <Grid>
14 <Border BorderBrush="Gray" BorderThickness="1">
15 <Grid>
16 <Grid.RowDefinitions>
17 <RowDefinition Height="100"/>
18 <RowDefinition Height="300"/>
19 </Grid.RowDefinitions>
20 <Grid.ColumnDefinitions>
21 <ColumnDefinition Width="*"></ColumnDefinition>
22 <ColumnDefinition Width="*"></ColumnDefinition>
23 <ColumnDefinition Width="*"></ColumnDefinition>
24 </Grid.ColumnDefinitions>
25
26 <Border Grid.ColumnSpan="3" Grid.Row="0" BorderBrush="LightGray" BorderThickness="0,0,0,1">
27 <Grid>
28 <Rectangle Fill="#FFD3D3D3" Height="60" VerticalAlignment="Center"/>
29
30 <Path Data="M117 91q-6-7 1-12l2-26q-3-1-2-7L85 34q-3 4-8 1L54 48q0 4-5 5L48 54 38 61l-1-1 10-7-3-3-10 6-1-1 10-6 1-1L44 47q1-4 5-4L75 28c2-4 6-5 10-2l40 15q9 0 6 9l2 29q7 5 0 13l14 8v7H101v-7Z"
31 Fill="#FF4F81BD" Stroke="Black" StrokeThickness="1"
32 HorizontalAlignment="Center" VerticalAlignment="Center"
33 Margin="-20,0,0,0" />
34 </Grid>
35 </Border>
36
37 <view:BoardStackControl Grid.Row="1" Grid.Column="0" BorderClicked="Rack1Control_BorderClicked" />
38 <view:BoardStackControl Grid.Row="1" Grid.Column="1" BorderClicked="Rack2Control_BorderClicked" />
39 <view:BoardStackControl Grid.Row="1" Grid.Column="2" BorderClicked="Rack3Control_BorderClicked" />
40 </Grid>
41 </Border>
42 </Grid>
43 </Window>

主窗口XAML.CS

 1 using System.Diagnostics;
2 using System.Text;
3 using System.Windows;
4 using System.Windows.Controls;
5 using System.Windows.Data;
6 using System.Windows.Documents;
7 using System.Windows.Input;
8 using System.Windows.Media;
9 using System.Windows.Media.Imaging;
10 using System.Windows.Navigation;
11 using System.Windows.Shapes;
12 using WpfApp1.Entities;
13 using WpfApp1.Views;
14
15 namespace WpfApp1
16 {
17 /// <summary>
18 /// Interaction logic for MainWindow.xaml
19 /// </summary>
20 public partial class MainWindow : Window
21 {
22 public MainWindow()
23 {
24 InitializeComponent();
25 }
26
27 private void Rack1Control_BorderClicked(object sender, RoutedEventArgs e)
28 {
29 if (e.OriginalSource is int index)
30 {
31 MessageBox.Show($"点击了第 1 个板栈的第 {index} 个 Border");
32 ExecuteMainWindowMethod(index);
33 }
34 }
35 private void Rack2Control_BorderClicked(object sender, RoutedEventArgs e)
36 {
37 if (e.OriginalSource is int index)
38 {
39 MessageBox.Show($"点击了第 2 个板栈的第 {index} 个 Border");
40 ExecuteMainWindowMethod(index);
41 }
42 }
43 private void Rack3Control_BorderClicked(object sender, RoutedEventArgs e)
44 {
45 if (e.OriginalSource is int index)
46 {
47 MessageBox.Show($"点击了第 3 个板栈的第 {index} 个 Border");
48 ExecuteMainWindowMethod(index);
49 }
50 }
51
52 private void ExecuteMainWindowMethod(int index)
53 {
54 //// 这里编写 MainWindow 的具体逻辑
55 //// 例如更新 UI 或处理业务逻辑
56 //var vm = (MainViewModel)this.DataContext;
57 //vm.RackClickedCommand.Execute($"2_{deviceCode}_{rackIndex}");
58 }
59 }
60 }

主窗口ViewModel

  1 using CommunityToolkit.Mvvm.ComponentModel;
2 using CommunityToolkit.Mvvm.Input;
3 using CommunityToolkit.Mvvm.Messaging;
4 using System;
5 using System.Collections.Generic;
6 using System.ComponentModel;
7 using System.Diagnostics;
8 using System.Runtime.CompilerServices;
9 using System.Windows.Input;
10 using WpfApp1.Entities;
11 using WpfApp1.Views;
12
13 namespace WpfApp1
14 {
15 public partial class MainViewModel
16 {
17
18 public MainViewModel()
19 {
20
21 LeftTubes3 = CreateCircularTubes(12, 18, 110, 50);
22
23 //IsActive = true;
24 }
25
26 #region 左侧板栈UI
27
28 public List<BoxPosition> LeftTubes3 { get; set; } = [];
29
30 private static List<BoxPosition> CreateCircularTubes(int count, int tubs, double outerRadius, double innerRadius)
31 {
32 var positions = new List<BoxPosition>();
33 double centerX = outerRadius;
34 double centerY = outerRadius;
35
36 for (int i = 0; i < count; i++)
37 {
38 // 计算角度 (360度均匀分布)
39 double angleDeg = 360.0 * i / count;
40 double angleRad = angleDeg * Math.PI / 180.0;
41
42 // 计算位置 (在内外半径之间)
43 double radius = (outerRadius + innerRadius) / 2;
44 double x = centerX + radius * Math.Cos(angleRad) - 17; // 25是料盒宽度的一半
45 double y = centerY + radius * Math.Sin(angleRad) - 25; // 35是料盒高度的一半
46
47 // 行数和列数
48 var rows = 2;
49 var cols = 3;
50 var margin = 2;
51 var width = 10;
52 var height = 10;
53 switch (tubs)
54 {
55 case 3:
56 rows = 1;
57 cols = 3;
58 margin = 2;
59 width = 10;
60 height = 10;
61 break;
62 //case 6:
63 // rows = 2;
64 // cols = 3;
65 // break;
66 case 12:
67 rows = 3;
68 cols = 4;
69 margin = 1;
70 width = 5;
71 height = 5;
72 break;
73 case 18:
74 rows = 3;
75 cols = 6;
76 margin = 1;
77 width = 4;
78 height = 4;
79 break;
80 case 96:
81 rows = 8;
82 cols = 12;
83 margin = 0;
84 width = 1;
85 height = 1;
86 break;
87 }
88
89 // 创建6个料管
90 var tubes = new List<Tube>();
91 for (int j = 0; j < tubs; j++)
92 {
93 tubes.Add(new Tube
94 {
95 Margin = margin,
96 Width = width,
97 Height = height,
98 });
99 }
100
101 positions.Add(new BoxPosition
102 {
103 Index = i + 1,
104 X = x,
105 Y = y,
106 Rows = rows,
107 Cols = cols,
108 Angle = angleDeg + 90, // 旋转角度等于位置角度
109 Tubes = tubes
110 });
111 }
112
113 return positions;
114 }
115
116
117 #endregion
118
119 }
120 }

Entities

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace WpfApp1.Entities
8 {
9 public class NestGroup
10 {
11 public List<BoxPosition> Nests { get; set; } = [];
12 }
13 public class BoxPosition
14 {
15 public int Index { get; set; }
16 public double X { get; set; }
17 public double Y { get; set; }
18 public double Angle { get; set; }
19 public int Rows { get; set; } = 2;
20 public int Cols { get; set; } = 3;
21 public List<Tube> Tubes { get; set; } = [];
22 }
23
24 public class Tube
25 {
26 public int Margin { get; set; } = 2;
27 public int Width { get; set; } = 10;
28 public int Height { get; set; } = 10;
29 }
30 }

WPF旋转板栈设计一例的更多相关文章

  1. 信息系统实践手记5-CACHE设计一例

    说明:信息系统实践手记系列是系笔者在平时研发中先后遇到的大小的问题,也许朴实和细微,但往往却是经常遇到的问题.笔者对其中比较典型的加以收集,描述,归纳和分享. 摘要:此文描述了笔者接触过的部分信息系统 ...

  2. Selenium WebDriver + Grid2 + RSpec之旅(五)---面向对象设计用例

    Selenium WebDriver + Grid2 + RSpec之旅(五) ----面向对象设计用例 前几节讲了怎么一步一步的从零开始到编写出一个简单的测试用例,这一节将要讲一下怎么让测试用例变得 ...

  3. cadence PCB板级设计

    总结PCB板框设计,定位孔的放置,以及布线区域和元件放置区域的放置,最重要的是层叠结构的设计.

  4. 2016-04-25-信息系统实践手记5-CACHE设计一例

    layout: post title: 2016-04-25-信息系统实践手记5-CACHE设计一例 key: 20160425 tags: 业务 场景 CACHE 系统分析 系统设计 缓存 modi ...

  5. 五步打造APP节日主题设计:以Lofter新年图标设计为例

    我们需要做有依据,有逻辑,有理念的设计,需要发散思维,整合创意,严谨输出,让设计经得起推敲 前言 ​ 2018年春节已远去,一直想把Lofter新年Logo设计思路分享给大家,直到现在才整理出来,希望 ...

  6. WPF旋转的界面实现

    原文:WPF旋转的界面实现 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/yangyisen0713/article/details/1821534 ...

  7. 痞子衡嵌入式:快速定位i.MXRT600板级设计ISP[2:0]启动模式引脚上电时序问题的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是一种快速定位i.MXRT600板级设计ISP[2-0]启动模式引脚上电时序问题的方法. 我们知道恩智浦i.MXRT600是主打音频市场的 ...

  8. WPF 多线程 UI:设计一个异步加载 UI 的容器

    对于 WPF 程序,如果你有某一个 UI 控件非常复杂,很有可能会卡住主 UI,给用户软件很卡的感受.但如果此时能有一个加载动画,那么就不会感受到那么卡顿了.UI 的卡住不同于 IO 操作或者密集的 ...

  9. C# WPF 粘贴板记录器

    工作学习中需要搜索很多资料,有建立文档对遇到过的问题进行记录,但是一来麻烦,二来有些当时认为不重要的事情,也许一段时间后认为是重要的,需要记录的,却又一时找不到,浪费时间做重复的事情.正好借着这个机会 ...

  10. [WPF自定义控件库]以Button为例谈谈如何模仿Aero2主题

    1. 为什么选择Aero2 除了以外观为卖点的控件库,WPF的控件库都默认使用"素颜"的外观,然后再提供一些主题包.这样做的最大好处是可以和原生控件或其它控件库兼容,而且对于大部分 ...

随机推荐

  1. Kafka优化提升

    一.如何优化kafka集群 1.吞吐量 2.低延时 生产者 a.batch.size=512kb或1MB(批量数据大小) b.buffer.memory=64M(缓冲区大小) c.linger.ms= ...

  2. Golang-包8

    http://c.biancheng.net/golang/package/ Go语言包的基本概念 Go语言是使用包来组织源代码的,包(package)是多个 Go 源码的集合,是一种高级的代码复用方 ...

  3. nginx里面的路径定位关键词root、alias

    nginx里面的路径定位关键词root.alias是有区别的: 设置请求资源的目录root / alias root:设置请求的根目录 语法 root path; 默认值 root html; 位置 ...

  4. codeblocks快捷键注释

    ctrl+shift+c可以快速注释掉多行. ctrl+shift+x可以取消注释

  5. win10 linux子系统的一些想法

    什么是linux子系统 具体的概念网上很多,作为个技术人简单粗暴来说就是微软脑子瓦特,突然爱上了linux, 可以在win10安装linux子系统 子系统不同于虚拟机,但是其优点是安装很快,对于新手和 ...

  6. Celery异步分布队列

    Celery分布式任务队列 一.Celery介绍celery periodic task Celery 是一个基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理,如果你的 ...

  7. LangChain基础篇 (04)

    LangChain 核心模块:Data Conneciton - Document Loaders 使用文档加载器从源中加载数据作为文档.一个文档是一段文字和相关的元数据. 如,有用于加载简单 .tx ...

  8. 爬虫无限Debugger解决方案

    爬虫无限Debugger解决方案 在应对网站中的debugger语句以防止爬虫被调试时,一些网站会在代码中插入这些断点以干扰调试行为. 一种极端但直接的方法是通过禁用浏览器的断点激活功能来绕过所有de ...

  9. Hbuilder使用快捷键

    Hbuilder的使用 1.Hbuilder基本操作​设置基本外观文字大小,申请账号.​2.Hbuilder快捷键​- 新建菜单: ctrl + N​- 新建: ctrl + N​- 关闭: ctrl ...

  10. 你还不会使用Pycham Remote development 打开远程主机工作目录吗?这篇文章帮你解决!

    前言 必备: 本地开发机与远程主机都要安装Pycharm专业版!!! 废话不多说直接开始!! 1.打开pycharm 2.依次点击File.Remote Development 3.依次点击SSH.N ...