Avalonia 基于MVVM的时间统计/系统时间显示 示例
基于MVVM,基于AI。
1.需求:
①显示系统当前时间
②显示系统运行时间(从系统运行开始统计)
③时间按秒(1000ms)刷新
页面目标效果:
2.代码实现:
2.1.页面代码MainWindow.axaml
<Window xmlns="https://github.com/avaloniaui"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"mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"x:Class="AvaloniaApplication2.Views.MainWindow"Icon="/Assets/avalonia-logo.ico"Title="测试页面的标题栏"Width="800"Height="600"WindowStartupLocation="CenterScreen"ExtendClientAreaToDecorationsHint="True"SystemDecorations="None"xmlns:vm="using:AvaloniaApplication2.ViewModels"><!--要引入数据模型--><Window.Styles><!-- 重写标题栏样式 --><Style Selector="Border#CustomTitleBar"><Setter Property="Background" Value="#1976D2" /> <!-- 深灰色标题栏 --></Style><!-- 关闭按钮样式 --><Style Selector="Button#CloseButton"><Setter Property="Margin" Value="0,0,0,0"></Setter><Setter Property="HorizontalAlignment" Value="Right"></Setter><Setter Property="Background" Value="Transparent" /><Setter Property="Foreground" Value="White" /><Setter Property="BorderThickness" Value="0" /><Setter Property="Width" Value="40" /><Setter Property="Height" Value="15" /></Style><Style Selector="Button#CloseButton:pointerover"><Setter Property="Foreground" Value="Red" /></Style><!-- 最大化和还原按钮 --><Style Selector="Button#MaximizeButton"><Setter Property="Margin" Value="470,0,0,0"></Setter><Setter Property="HorizontalAlignment" Value="Right"></Setter><Setter Property="Background" Value="Transparent" /><Setter Property="Foreground" Value="White" /><Setter Property="BorderThickness" Value="0" /><Setter Property="Width" Value="40" /><Setter Property="Height" Value="20" /></Style><Style Selector="Button#MaximizeButton:pointerover"><Setter Property="Foreground" Value="Red" /></Style></Window.Styles><Viewbox Stretch="Fill"><Grid RowDefinitions="0.5*,1.2*,10*,0.5*" ShowGridLines="True" Background="AliceBlue"><!-- 第1行,自定义标题栏 --><Border Grid.Row="0" Background="CadetBlue"PointerPressed="TitleBar_PointerPressed"Name="CustomTitleBar"Height="25"><DockPanel><!-- Icon,窗口标题 --><Image Source="/Assets/avalonia-logo.ico" Width="25" Height="19" MinHeight="0" MinWidth="0"></Image><TextBlock Text="{Binding Title, RelativeSource={RelativeSource AncestorType=Window}}"Foreground="White"VerticalAlignment="Center"Margin="5,0,5,0"FontSize="11"TextTrimming="CharacterEllipsis" /><!--窗口控制按钮--><StackPanel DockPanel.Dock="Right" Orientation="Horizontal"><!-- 最大化/还原按钮 --><Button Name="MaximizeButton" Content="🗖"Click="MaximizeButton_Click"ToolTip.Tip="最大化"MinHeight="0"MinWidth="0" /><!-- 关闭按钮 --><Button Name="CloseButton" Content="✕"Click="CloseButton_Click"ToolTip.Tip="关闭"MinHeight="0"MinWidth="0" /></StackPanel></DockPanel></Border><!-- 第2行内容区 --><Border Grid.Row="1" Background="Aquamarine"Height="59"><Border><TextBlock Text="这是第2行内容区" /></Border></Border><!-- 第3行内容区 --><Border Grid.Row="2" Background="Bisque"Height="491.8"><Border><Grid RowDefinitions="*,*" ShowGridLines="True"><!-- 系统当前时间占位 --><Border><WrapPanel><TextBlock FontSize="20"Text="系统当前日期时间 : "></TextBlock><!-- x:DataType="vm:MainWindowViewModel" 数据类型也可以在Window标签属性中整体声明--><TextBlock FontSize="20"x:DataType="vm:MainWindowViewModel"Text="{Binding CurrentTime}"></TextBlock></WrapPanel></Border><!-- 系统运行时间统计占位 --><Border Grid.Row="1"><WrapPanel><TextBlock FontSize="20"Text="系统累计运行时间统计 : "></TextBlock><TextBlock FontSize="20"x:DataType="vm:MainWindowViewModel"Text="{Binding Runtime}"></TextBlock></WrapPanel></Border></Grid></Border></Border><!-- 第4行内容区 --><Border Grid.Row="3" Background="BlueViolet"Height="25.6"><Border><TextBlock Text="这是第4行内容区" /></Border></Border></Grid></Viewbox></Window>
2.2.代码后置MainWindow.axaml.cs
using System;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using AvaloniaApplication2.ViewModels;namespace AvaloniaApplication2.Views;public partial class MainWindow : Window
{//VM对象private readonly MainWindowViewModel _viewModel;public MainWindow(){InitializeComponent();// 初始化 ViewModel_viewModel = new MainWindowViewModel();DataContext = _viewModel;}//管理VM对象protected override void OnClosed(EventArgs e){base.OnClosed(e);_viewModel.Dispose();}// 添加窗口拖动支持private void TitleBar_PointerPressed(object sender, PointerPressedEventArgs e){if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed){BeginMoveDrag(e);}}// 关闭按钮 X 点击事件private void CloseButton_Click(object sender, RoutedEventArgs e){Close();}// 最大化/还原按钮点击事件private void MaximizeButton_Click(object sender, RoutedEventArgs e){if (sender is Button button){if (WindowState == WindowState.Normal){WindowState = WindowState.Maximized;button.Content = "🗗"; // 还原图标ToolTip.SetTip(button, "还原"); // 正确设置工具提示的方式}else{WindowState = WindowState.Normal;button.Content = "🗖"; // 最大化图标ToolTip.SetTip(button, "最大化"); // 正确设置工具提示的方式}}}}
2.3.视图模型VM类MainWindowViewModel
using Avalonia.Threading;
using System;
using System.ComponentModel;
using System.Diagnostics;namespace AvaloniaApplication2.ViewModels;public partial class MainWindowViewModel : ViewModelBase,INotifyPropertyChanged, IDisposable
{public string Greeting { get; } = "Welcome to Avalonia!";private readonly DispatcherTimer _clockTimer;private readonly DispatcherTimer _runtimeTimer;private readonly Stopwatch _runtimeStopwatch;private string _currentTime;private string _runtime;public MainWindowViewModel(){// 初始化当前时间CurrentTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");// 初始化运行时间_runtimeStopwatch = Stopwatch.StartNew();Runtime = "00:00:00";// 创建时钟定时器(每秒更新)_clockTimer = new DispatcherTimer{Interval = TimeSpan.FromSeconds(1)//单位秒};_clockTimer.Tick += ClockTimer_Tick;_clockTimer.Start();// 创建运行时间定时器(每秒更新)_runtimeTimer = new DispatcherTimer{Interval = TimeSpan.FromSeconds(1)//单位秒};_runtimeTimer.Tick += RuntimeTimer_Tick;_runtimeTimer.Start();}public string CurrentTime{get => _currentTime;set{_currentTime = value;OnPropertyChanged(nameof(CurrentTime));}}public string Runtime{get => _runtime;set{_runtime = value;OnPropertyChanged(nameof(Runtime));}}private void ClockTimer_Tick(object sender, EventArgs e){CurrentTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");}private void RuntimeTimer_Tick(object sender, EventArgs e){Runtime = _runtimeStopwatch.Elapsed.ToString(@"hh\:mm\:ss");}public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged(string propertyName){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}public void Dispose(){_clockTimer.Stop();_runtimeTimer.Stop();_runtimeStopwatch.Stop();_clockTimer.Tick -= ClockTimer_Tick;_runtimeTimer.Tick -= RuntimeTimer_Tick;}
}
3.最终效果:
4.代码分析
基于MVVM,还不会,全靠AI,等学完了WPF再回来品味这坨代码🤭
5.可能存在的问题
假设该软件可能一直长久运行,但是这个累计运行时间的格式到一定程度上会归零(统计上限),暂不清楚该怎么解决,具体的有需要的话可以跟负责人对一下。