扔飒 发表于 2025-5-29 14:10:59

WPF旋转板栈设计一例

效果图
项目中需要做一个机台的平面视图,点击其中一个料盒时,弹出该料盒的料管列表,用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         
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                        
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         
86
87   </Grid>
88 </UserControl>
89
90   View Code用户控件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 }View Code主窗口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>View Code主窗口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 }View Code主窗口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 }View CodeEntities
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 }View Code 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: WPF旋转板栈设计一例