找回密码
 立即注册
首页 资源区 代码 WPF旋转板栈设计一例

WPF旋转板栈设计一例

扔飒 2025-5-29 14:10:59
效果图
项目中需要做一个机台的平面视图,点击其中一个料盒时,弹出该料盒的料管列表,用WPF示例做了一下,效果如下:
1.png

用户控件XAML
2.gif
3.gif
  1. 1 <UserControl x:Class="WpfApp1.Views.BoardStackControl"
  2. 2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. 3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. 4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  5. 5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6. 6              xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
  7. 7              xmlns:local="clr-namespace:WpfApp1.Views"
  8. 8              xmlns:wpfapp1="clr-namespace:WpfApp1"
  9. 9              d:DataContext="{d:DesignInstance Type=wpfapp1:MainViewModel}"
  10. 10              Width="224" Height="300"
  11. 11              mc:Ignorable="d"
  12. 12              d:DesignHeight="300" d:DesignWidth="250">
  13. 13     <UserControl.DataContext>
  14. 14         <wpfapp1:MainViewModel />
  15. 15     </UserControl.DataContext>
  16. 16     <Grid>
  17. 17         
  18. 25         <Border Margin="1">
  19. 26             <Grid Width="220" Height="220">
  20. 27                 <Ellipse Stroke="#dcdfe3" StrokeThickness="3"  Width="220" Height="220"/>
  21. 28                 <Ellipse Stroke="#dcdfe3" StrokeThickness="3"  Width="80" Height="80" HorizontalAlignment="Center" VerticalAlignment="Center"/>
  22. 29                 <ItemsControl ItemsSource="{Binding LeftTubes3}">
  23. 30                     <ItemsControl.ItemsPanel>
  24. 31                         <ItemsPanelTemplate>
  25. 32                             <Canvas/>
  26. 33                         </ItemsPanelTemplate>
  27. 34                     </ItemsControl.ItemsPanel>
  28. 35                     <ItemsControl.ItemContainerStyle>
  29. 36                        
  30. 46                     </ItemsControl.ItemContainerStyle>
  31. 47                     <ItemsControl.ItemTemplate>
  32. 48                         <DataTemplate>
  33. 49                             <Grid>
  34. 50                                 <Border Width="35" Height="50" Tag="{Binding .}" x:Name="animatedBorder" MouseLeftButtonDown="Border_MouseLeftButtonDown"
  35. 51                         CornerRadius="3"  Background="#FFE6E6E6" BorderBrush="Gray" BorderThickness="1">
  36. 52                                     <ItemsControl ItemsSource="{Binding Tubes}" Margin="2" IsHitTestVisible="False">
  37. 53                                         <ItemsControl.ItemsPanel>
  38. 54                                             <ItemsPanelTemplate>
  39. 55                                                 <UniformGrid Columns="{Binding Rows}" Rows="{Binding Cols}" IsHitTestVisible="False"/>
  40. 56                                             </ItemsPanelTemplate>
  41. 57                                         </ItemsControl.ItemsPanel>
  42. 58                                         <ItemsControl.ItemTemplate>
  43. 59                                             <DataTemplate>
  44. 60                                                 <Ellipse Width="{Binding Width}" Height="{Binding Height}" Fill="#FF4F81BD"  Margin="{Binding Margin}" Stroke="Black" StrokeThickness="0.5" IsHitTestVisible="False"/>
  45. 61                                             </DataTemplate>
  46. 62                                         </ItemsControl.ItemTemplate>
  47. 63                                     </ItemsControl>
  48. 64                                     <Border.Triggers>
  49. 65                                         <EventTrigger RoutedEvent="MouseLeftButtonUp">
  50. 66                                             <BeginStoryboard>
  51. 67                                                 <Storyboard>
  52. 68                                                     <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0.5" Duration="0:0:0.1" AutoReverse="True"/>
  53. 69                                                 </Storyboard>
  54. 70                                             </BeginStoryboard>
  55. 71                                         </EventTrigger>
  56. 72                                     </Border.Triggers>
  57. 73                                 </Border>
  58. 74                                 <Border Width="20" Height="20" CornerRadius="10"  Background="#FF4F81BD" BorderBrush="White" BorderThickness="1" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,-10,0,0">
  59. 75                                     <TextBlock Text="{Binding Index}"   Foreground="White" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
  60. 76                                 </Border>
  61. 77                             </Grid>
  62. 78                         </DataTemplate>
  63. 79                     </ItemsControl.ItemTemplate>
  64. 80                 </ItemsControl>
  65. 81             </Grid>
  66. 82         </Border>
  67. 83         
  68. 86
  69. 87     </Grid>
  70. 88 </UserControl>
  71. 89
  72. 90     
复制代码
View Code用户控件XMAL.CS
4.gif
5.gif
  1. 1 using CommunityToolkit.Mvvm.Messaging;
  2. 2 using Microsoft.Extensions.Logging;
  3. 3 using System.Collections.ObjectModel;
  4. 4 using System.Diagnostics;
  5. 5 using System.Windows;
  6. 6 using System.Windows.Controls;
  7. 7 using System.Windows.Input;
  8. 8 using System.Windows.Media;
  9. 9 using WpfApp1.Entities;
  10. 10
  11. 11 namespace WpfApp1.Views;
  12. 12
  13. 13 public partial class BoardStackControl : UserControl
  14. 14 {
  15. 15     public BoardStackControl()
  16. 16     {
  17. 17         InitializeComponent();
  18. 18
  19. 19     }
  20. 20
  21. 21     public static readonly RoutedEvent BorderClickedEvent =
  22. 22         EventManager.RegisterRoutedEvent(
  23. 23             "BorderClicked",
  24. 24             RoutingStrategy.Bubble,
  25. 25             typeof(RoutedEventHandler),
  26. 26             typeof(BoardStackControl)
  27. 27         );
  28. 28
  29. 29     public event RoutedEventHandler BorderClicked
  30. 30     {
  31. 31         add => AddHandler(BorderClickedEvent, value);
  32. 32         remove => RemoveHandler(BorderClickedEvent, value);
  33. 33     }
  34. 34
  35. 35     private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  36. 36     {
  37. 37         if (sender is Border border && border.DataContext is BoxPosition boxPosition)
  38. 38         {
  39. 39             // 触发路由事件,并携带索引
  40. 40             var args = new RoutedEventArgs(BorderClickedEvent, boxPosition.Index);
  41. 41             RaiseEvent(args);
  42. 42             e.Handled = true;
  43. 43         }
  44. 44     }
  45. 45
  46. 46 }
复制代码
View Code主窗口XAML
6.gif
7.gif
  1. 1 <Window x:Class="WpfApp1.MainWindow"
  2. 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. 6         xmlns:local="clr-namespace:WpfApp1"
  7. 7         xmlns:view="clr-namespace:WpfApp1.Views"
  8. 8         mc:Ignorable="d"
  9. 9         Title="MainWindow" Height="450" Width="800">
  10. 10     <Window.DataContext>
  11. 11         <local:MainViewModel />
  12. 12     </Window.DataContext>
  13. 13     <Grid>
  14. 14         <Border BorderBrush="Gray" BorderThickness="1">
  15. 15             <Grid>
  16. 16                 <Grid.RowDefinitions>
  17. 17                     <RowDefinition Height="100"/>
  18. 18                     <RowDefinition Height="300"/>
  19. 19                 </Grid.RowDefinitions>
  20. 20                 <Grid.ColumnDefinitions>
  21. 21                     <ColumnDefinition Width="*"></ColumnDefinition>
  22. 22                     <ColumnDefinition Width="*"></ColumnDefinition>
  23. 23                     <ColumnDefinition Width="*"></ColumnDefinition>
  24. 24                 </Grid.ColumnDefinitions>
  25. 25
  26. 26                 <Border Grid.ColumnSpan="3" Grid.Row="0"  BorderBrush="LightGray" BorderThickness="0,0,0,1">
  27. 27                     <Grid>
  28. 28                         <Rectangle Fill="#FFD3D3D3" Height="60" VerticalAlignment="Center"/>
  29. 29
  30. 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. 31                           Fill="#FF4F81BD" Stroke="Black" StrokeThickness="1"
  32. 32                           HorizontalAlignment="Center" VerticalAlignment="Center"
  33. 33                           Margin="-20,0,0,0" />
  34. 34                     </Grid>
  35. 35                 </Border>
  36. 36
  37. 37                 <view:BoardStackControl Grid.Row="1" Grid.Column="0" BorderClicked="Rack1Control_BorderClicked" />
  38. 38                 <view:BoardStackControl Grid.Row="1" Grid.Column="1" BorderClicked="Rack2Control_BorderClicked" />
  39. 39                 <view:BoardStackControl Grid.Row="1" Grid.Column="2" BorderClicked="Rack3Control_BorderClicked" />
  40. 40             </Grid>
  41. 41         </Border>
  42. 42     </Grid>
  43. 43 </Window>
复制代码
View Code主窗口XAML.CS
8.gif
9.gif
  1. 1 using System.Diagnostics;
  2. 2 using System.Text;
  3. 3 using System.Windows;
  4. 4 using System.Windows.Controls;
  5. 5 using System.Windows.Data;
  6. 6 using System.Windows.Documents;
  7. 7 using System.Windows.Input;
  8. 8 using System.Windows.Media;
  9. 9 using System.Windows.Media.Imaging;
  10. 10 using System.Windows.Navigation;
  11. 11 using System.Windows.Shapes;
  12. 12 using WpfApp1.Entities;
  13. 13 using WpfApp1.Views;
  14. 14
  15. 15 namespace WpfApp1
  16. 16 {
  17. 17     /// <summary>
  18. 18     /// Interaction logic for MainWindow.xaml
  19. 19     /// </summary>
  20. 20     public partial class MainWindow : Window
  21. 21     {
  22. 22         public MainWindow()
  23. 23         {
  24. 24             InitializeComponent();
  25. 25         }
  26. 26
  27. 27         private void Rack1Control_BorderClicked(object sender, RoutedEventArgs e)
  28. 28         {
  29. 29             if (e.OriginalSource is int index)
  30. 30             {
  31. 31                 MessageBox.Show($"点击了第 1 个板栈的第 {index} 个 Border");
  32. 32                 ExecuteMainWindowMethod(index);
  33. 33             }
  34. 34         }
  35. 35         private void Rack2Control_BorderClicked(object sender, RoutedEventArgs e)
  36. 36         {
  37. 37             if (e.OriginalSource is int index)
  38. 38             {
  39. 39                 MessageBox.Show($"点击了第 2 个板栈的第 {index} 个 Border");
  40. 40                 ExecuteMainWindowMethod(index);
  41. 41             }
  42. 42         }
  43. 43         private void Rack3Control_BorderClicked(object sender, RoutedEventArgs e)
  44. 44         {
  45. 45             if (e.OriginalSource is int index)
  46. 46             {
  47. 47                 MessageBox.Show($"点击了第 3 个板栈的第 {index} 个 Border");
  48. 48                 ExecuteMainWindowMethod(index);
  49. 49             }
  50. 50         }
  51. 51
  52. 52         private void ExecuteMainWindowMethod(int index)
  53. 53         {
  54. 54             //// 这里编写 MainWindow 的具体逻辑
  55. 55             //// 例如更新 UI 或处理业务逻辑
  56. 56             //var vm = (MainViewModel)this.DataContext;
  57. 57             //vm.RackClickedCommand.Execute($"2_{deviceCode}_{rackIndex}");
  58. 58         }
  59. 59     }
  60. 60 }
复制代码
View Code主窗口ViewModel
10.gif
11.gif
  1.   1 using CommunityToolkit.Mvvm.ComponentModel;
  2.   2 using CommunityToolkit.Mvvm.Input;
  3.   3 using CommunityToolkit.Mvvm.Messaging;
  4.   4 using System;
  5.   5 using System.Collections.Generic;
  6.   6 using System.ComponentModel;
  7.   7 using System.Diagnostics;
  8.   8 using System.Runtime.CompilerServices;
  9.   9 using System.Windows.Input;
  10. 10 using WpfApp1.Entities;
  11. 11 using WpfApp1.Views;
  12. 12
  13. 13 namespace WpfApp1
  14. 14 {
  15. 15     public partial class MainViewModel
  16. 16     {
  17. 17
  18. 18         public MainViewModel()
  19. 19         {
  20. 20
  21. 21             LeftTubes3 = CreateCircularTubes(12, 18, 110, 50);
  22. 22
  23. 23             //IsActive = true;
  24. 24         }
  25. 25
  26. 26         #region 左侧板栈UI
  27. 27
  28. 28         public List<BoxPosition> LeftTubes3 { get; set; } = [];
  29. 29
  30. 30         private static List<BoxPosition> CreateCircularTubes(int count, int tubs, double outerRadius, double innerRadius)
  31. 31         {
  32. 32             var positions = new List<BoxPosition>();
  33. 33             double centerX = outerRadius;
  34. 34             double centerY = outerRadius;
  35. 35
  36. 36             for (int i = 0; i < count; i++)
  37. 37             {
  38. 38                 // 计算角度 (360度均匀分布)
  39. 39                 double angleDeg = 360.0 * i / count;
  40. 40                 double angleRad = angleDeg * Math.PI / 180.0;
  41. 41
  42. 42                 // 计算位置 (在内外半径之间)
  43. 43                 double radius = (outerRadius + innerRadius) / 2;
  44. 44                 double x = centerX + radius * Math.Cos(angleRad) - 17; // 25是料盒宽度的一半
  45. 45                 double y = centerY + radius * Math.Sin(angleRad) - 25; // 35是料盒高度的一半
  46. 46
  47. 47                 // 行数和列数
  48. 48                 var rows = 2;
  49. 49                 var cols = 3;
  50. 50                 var margin = 2;
  51. 51                 var width = 10;
  52. 52                 var height = 10;
  53. 53                 switch (tubs)
  54. 54                 {
  55. 55                     case 3:
  56. 56                         rows = 1;
  57. 57                         cols = 3;
  58. 58                         margin = 2;
  59. 59                         width = 10;
  60. 60                         height = 10;
  61. 61                         break;
  62. 62                     //case 6:
  63. 63                     //    rows = 2;
  64. 64                     //    cols = 3;
  65. 65                     //    break;
  66. 66                     case 12:
  67. 67                         rows = 3;
  68. 68                         cols = 4;
  69. 69                         margin = 1;
  70. 70                         width = 5;
  71. 71                         height = 5;
  72. 72                         break;
  73. 73                     case 18:
  74. 74                         rows = 3;
  75. 75                         cols = 6;
  76. 76                         margin = 1;
  77. 77                         width = 4;
  78. 78                         height = 4;
  79. 79                         break;
  80. 80                     case 96:
  81. 81                         rows = 8;
  82. 82                         cols = 12;
  83. 83                         margin = 0;
  84. 84                         width = 1;
  85. 85                         height = 1;
  86. 86                         break;
  87. 87                 }
  88. 88
  89. 89                 // 创建6个料管
  90. 90                 var tubes = new List<Tube>();
  91. 91                 for (int j = 0; j < tubs; j++)
  92. 92                 {
  93. 93                     tubes.Add(new Tube
  94. 94                     {
  95. 95                         Margin = margin,
  96. 96                         Width = width,
  97. 97                         Height = height,
  98. 98                     });
  99. 99                 }
  100. 100
  101. 101                 positions.Add(new BoxPosition
  102. 102                 {
  103. 103                     Index = i + 1,
  104. 104                     X = x,
  105. 105                     Y = y,
  106. 106                     Rows = rows,
  107. 107                     Cols = cols,
  108. 108                     Angle = angleDeg + 90, // 旋转角度等于位置角度
  109. 109                     Tubes = tubes
  110. 110                 });
  111. 111             }
  112. 112
  113. 113             return positions;
  114. 114         }
  115. 115
  116. 116
  117. 117         #endregion
  118. 118
  119. 119     }
  120. 120 }
复制代码
View CodeEntities
12.gif
13.gif
  1. 1 using System;
  2. 2 using System.Collections.Generic;
  3. 3 using System.Linq;
  4. 4 using System.Text;
  5. 5 using System.Threading.Tasks;
  6. 6
  7. 7 namespace WpfApp1.Entities
  8. 8 {
  9. 9     public class NestGroup
  10. 10     {
  11. 11         public List<BoxPosition> Nests { get; set; } = [];
  12. 12     }
  13. 13     public class BoxPosition
  14. 14     {
  15. 15         public int Index { get; set; }
  16. 16         public double X { get; set; }
  17. 17         public double Y { get; set; }
  18. 18         public double Angle { get; set; }
  19. 19         public int Rows { get; set; } = 2;
  20. 20         public int Cols { get; set; } = 3;
  21. 21         public List<Tube> Tubes { get; set; } = [];
  22. 22     }
  23. 23
  24. 24     public class Tube
  25. 25     {
  26. 26         public int Margin { get; set; } = 2;
  27. 27         public int Width { get; set; } = 10;
  28. 28         public int Height { get; set; } = 10;
  29. 29     }
  30. 30 }
复制代码
View Code 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册