the paint points of xaml

本文探讨了使用XAML进行UI开发时遇到的多个痛点,包括控制构造的限制、动态GUI的难以实现、布局复杂性、编译时检查不足等问题,并提出了改进的方向。
Pain Point 1: XAML always create the controls by its default constructor

This means, you need to have a default constructor for you control, and the constructor will always be used by XAML. So, you can not use constructor dependency injection to pass things like services, gateways to your control. Also, you will not have chance to pass data in constructor, although the data might be must-have for the specific type of control

Paint Point 2: can not control XAML to create or not to create some part of GUI

Sometimes, the GUI is not static. It could be dynamic because the GUI would be different for the data it is presenting, such as for a meeting in the past it should show a adding note button, for a meeting in the future it should not. And more often, the security control requires the GUI to be different according to the role.

Paint Point 3: XAML is using XML, which contains too many visual noise

compared to things like YAML, XML is definitely not very friendly to our eyes. The things worse than XML I can come up is the braces of Lisp. Also, XML makes it harder to edit manually

Paint Point 4: Layouting in Grid

Using grid layout currently requires you to specify the row and column for all the children of a grid. It is very error-prone when the grid becomes large. But grid is a must-have for any non-trivial GUI, and there is not replacement for it yet.

Paint Point 5: Things not checked in compiling time

There are lots of things not checked by the compiler in XAML. Things like binding, resource looking up for example. And it is harder to cross reference between xaml and code.

Paint Point 6: More files

one file for xaml one file for cs. It requires more steps to create a new user control and is confusing to new comers.

Paint Point 7: Separating concerns

the default way events get handled is in the partial class of the XAML. It is not a good way of separating concerns and not good oo design. the windows and user controls usually doing too much in rich client application. It is not the fault of XAML in general, but it is not promoting a good model either by its weird way of hooking up event in xaml.

Paint Point 8: Hard to test

It is hard to test in many ways. First, not easy to inject dependency means you can not mock those expensive things like network connection. Second, creating a real window is taking more than ten seconds. Third, many things are in a static singleton model like resource looking up and the single instance application object.
using Microsoft.Maui.Graphics; using Microsoft.Maui.Graphics.Platform; public partial class EcgPage : ContentPage { public EcgPage() { InitializeComponent(); BindingContext = new EcgViewModel(); DrawEcgChart(); } private void DrawEcgChart() { var viewModel = BindingContext as EcgViewModel; if (viewModel == null) return; using (var canvas = new SkiaSharp.SKCanvasView()) { canvas.PaintSurface += (sender, e) => { var surface = e.Surface; var canvas = surface.Canvas; canvas.Clear(SKColors.White); var paint = new SKPaint { Color = SKColors.Blue, StrokeWidth = 2, IsAntialias = true }; var path = new SKPath(); var dataPoints = viewModel.EcgDataList; if (dataPoints.Count > 0) { var width = canvas.LocalClipBounds.Width; var height = canvas.LocalClipBounds.Height; var scaleX = width / dataPoints.Count; var scaleY = height / 2; path.MoveTo(0, (float)(height / 2 - dataPoints[0].Voltage * scaleY)); for (int i = 1; i < dataPoints.Count; i++) { var x = i * scaleX; var y = (float)(height / 2 - dataPoints[i].Voltage * scaleY); path.LineTo(x, y); } canvas.DrawPath(path, paint); } }; EcgChart.Children.Add(canvas); } } } 严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动) CS1061 “BoxView”未包含“Children”的定义,并且找不到可接受第一个“BoxView”类型参数的可访问扩展方法“Children”(是否缺少 using 指令或程序集引用?) RuiChao.SixWMT (net8.0-android) D:\SixWMT\RuiChao.SixWMT\RuiChao.SixWMT\Pages\CommonRunning6MWTPage.xaml.cs 67
07-26
图表的中文格式出错,全部为口字。 private void InitializeChart() { try { var colors = GenerateColors(64); for (int i = 0; i < 64; i++) { int moduleGroup = (i / 8) + 1; int boardAddress = i % 8; var series = new LineSeries<double> { Name = $"模块{moduleGroup}-{boardAddress}", Values = new ObservableCollection<double>(), // 关键修改 Fill = null, GeometrySize = 0, LineSmoothness = 0, // 如果需要颜色: Stroke = new SolidColorPaint(SKColors.Red) { StrokeThickness = 1 } }; _chartSeries.Add(series); // 移除自定义 ChartPoint 字典,不再需要用这个 } _cartesianChart = new CartesianChart { Series = _chartSeries, XAxes = new[] { new Axis { Name = "时间", NameTextSize = 12, // 如果是时间轴,建议配置为 DateTimeAxis // 但为简单起见,保持索引模式 } }, YAxes = new[] { new Axis { Name = "磁场强度 (μT)", NameTextSize = 12, MinStep = 1 } }, LegendPosition = LiveChartsCore.Measure.LegendPosition.Hidden, Margin = new Thickness(10), Height = 300 }; // 必须设置宽高,否则 Canvas 中尺寸为 0 _cartesianChart.Width = ChartCanvas.ActualWidth > 0 ? ChartCanvas.ActualWidth : 800; _cartesianChart.Height = 300; ChartCanvas.Children.Clear(); ChartCanvas.Children.Add(_cartesianChart); } catch (Exception ex) { _logger.LogError(ex, "Failed to initialize chart"); } } 程序退出时,软件报错: System.NullReferenceException:“Object reference not set to an instance of an object.” System.Windows.Application.Current.get 返回 null。 // 使用UI线程更新集合 System.Windows.Application.Current.Dispatcher.Invoke(() => { // 更新对应模块的数据 if (data.BoardAddress >= 0 && data.BoardAddress < 8) { AllModulesData[moduleIndex][data.BoardAddress] = data; } // 同时更新总数据列表 var existingData = TMRDataList.FirstOrDefault(d => d.ModuleGroup == data.ModuleGroup && d.BoardAddress == data.BoardAddress); if (existingData != null) { var index = TMRDataList.IndexOf(existingData); TMRDataList[index] = data; } else { TMRDataList.Add(data); } // 更新图表数据 UpdateChartData(data);图表的中文格式出错,全部为口字。 程序退出时,软件报错: System.NullReferenceException:“Object reference not set to an instance of an object.” System.Windows.Application.Current.get 返回 null。 // 使用UI线程更新集合 System.Windows.Application.Current.Dispatcher.Invoke(() => { // 更新对应模块的数据 if (data.BoardAddress >= 0 && data.BoardAddress < 8) { AllModulesData[moduleIndex][data.BoardAddress] = data; } // 同时更新总数据列表 var existingData = TMRDataList.FirstOrDefault(d => d.ModuleGroup == data.ModuleGroup && d.BoardAddress == data.BoardAddress); if (existingData != null) { var index = TMRDataList.IndexOf(existingData); TMRDataList[index] = data; } else { TMRDataList.Add(data); } // 更新图表数据 UpdateChartData(data); }); });
11-12
基于51单片机,实现对直流电机的调速、测速以及正反转控制。项目包含完整的仿真文件、源程序、原理图和PCB设计文件,适合学习和实践51单片机在电机控制方面的应用。 功能特点 调速控制:通过按键调整PWM占空比,实现电机的速度调节。 测速功能:采用霍尔传感器非接触式测速,实时显示电机转速。 正反转控制:通过按键切换电机的正转和反转状态。 LCD显示:使用LCD1602液晶显示屏,显示当前的转速和PWM占空比。 硬件组成 主控制器:STC89C51/52单片机(与AT89S51/52、AT89C51/52通用)。 测速传感器:霍尔传感器,用于非接触式测速。 显示模块:LCD1602液晶显示屏,显示转速和占空比。 电机驱动:采用双H桥电路,控制电机的正反转和调速。 软件设计 编程语言:C语言。 开发环境:Keil uVision。 仿真工具:Proteus。 使用说明 液晶屏显示: 第一行显示电机转速(单位:转/分)。 第二行显示PWM占空比(0~100%)。 按键功能: 1键:加速键,短按占空比加1,长按连续加。 2键:减速键,短按占空比减1,长按连续减。 3键:反转切换键,按下后电机反转。 4键:正转切换键,按下后电机正转。 5键:开始暂停键,按一下开始,再按一下暂停。 注意事项 磁铁和霍尔元件的距离应保持在2mm左右,过近可能会在电机转动时碰到霍尔元件,过远则可能导致霍尔元件无法检测到磁铁。 资源文件 仿真文件:Proteus仿真文件,用于模拟电机控制系统的运行。 源程序:Keil uVision项目文件,包含完整的C语言源代码。 原理图:电路设计原理图,详细展示了各模块的连接方式。 PCB设计:PCB布局文件,可用于实际电路板的制作。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值