Avalonia+ReactiveUI实现记录自动更新

Avalonia+ReactiveUI+Sourcegenerators实现记录条数的自动更新

1、项目文件

csharp 复制代码
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <LangVersion>latest</LangVersion>
    <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
  </PropertyGroup>

  <ItemGroup>
    <AvaloniaResource Include="Assets\**" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Avalonia" Version="11.3.6" />
    <PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.6" />
    <PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.6" />
    <PackageReference Include="Avalonia.ReactiveUI" Version="11.3.6" />
    <!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
    <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.3.6" />
    <PackageReference Include="ReactiveUI.SourceGenerators" Version="2.4.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>
</Project>

2、Model

csharp 复制代码
using ReactiveUI;
using ReactiveUI.SourceGenerators;

namespace AvaRea.Models
{
    public partial class Person:ReactiveObject
    {
        [Reactive]private string _name;
        [Reactive] private int _age;
        [Reactive] private string _email;
    }
}

3、ViewModel (使用 ReactiveUI Source Generators)

csharp 复制代码
using AvaRea.Models;
using DynamicData;
using DynamicData.Binding;
using ReactiveUI;
using ReactiveUI.SourceGenerators;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reactive.Linq;
namespace AvaRea.ViewModels;


public partial class MainViewModel : ViewModelBase
{
    private int index = 0;
    public ObservableCollection<Person> People { get; set; } = new();
    [ObservableAsProperty]
    private int _peopleCount;
    [Reactive]
    private Person _selectedPerson;
    [ReactiveCommand]
    private void AddPerson()
    {
        People.Add(new Person { Name = $"王五{index++}", Age = 28+index, Email = $"mysoilost{index}@163.com" });
    }
    public MainViewModel()
    {
        // 初始化数据
        var people = new[]
        {
            new Person { Name = "张三", Age = 25, Email = "zhang@example.com" },
            new Person { Name = "李四", Age = 30, Email = "li@example.com" }
        };
        People.AddRange(people);
        // 监听集合变化
        _peopleCountHelper = People
            .ToObservableChangeSet()
            .Select(_ => People.Count)  // 每次变化时获取最新的数量
            .ToProperty(this, x => x.PeopleCount);
    }
}

using ReactiveUI;

namespace AvaRea.ViewModels;

public class ViewModelBase : ReactiveObject
{
}

4、View

csharp 复制代码
<Window
    x:Class="AvaRea.Views.MainView"
    xmlns="https://github.com/avaloniaui"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:model="clr-namespace:AvaRea.Models"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:AvaRea.ViewModels"
    d:DesignHeight="450"
    d:DesignWidth="800"
    x:DataType="vm:MainViewModel"
    mc:Ignorable="d">
    <Window.DataTemplates>
        <DataTemplate DataType="model:Person">
            <StackPanel
                Margin="5"
                Orientation="Horizontal"
                Spacing="10">
                <Ellipse
                    Width="32"
                    Height="32"
                    Fill="LightBlue" />
                <StackPanel>
                    <TextBlock FontWeight="Bold" Text="{Binding Name}" />
                    <TextBlock
                        FontSize="12"
                        Foreground="Gray"
                        Text="{Binding Email}" />
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </Window.DataTemplates>
    <Design.DataContext>
        <!--
            This only sets the DataContext for the previewer in an IDE,
            to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs)
        -->
        <vm:MainViewModel />
    </Design.DataContext>
    <StackPanel>
        <TextBlock Text="{Binding PeopleCount}" />
        <ListBox
            ItemsSource="{Binding People}"
            SelectedItem="{Binding SelectedPerson}" />
        <Button Command="{Binding AddPersonCommand}" Content="增加" />
    </StackPanel>
</Window>

using Avalonia.Controls;


namespace AvaRea.Views;

public partial class MainView : Window
{
    public MainView()
    {
        InitializeComponent();
    }
}

5、App.axaml

csharp 复制代码
<Application xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="AvaRea.App"
             RequestedThemeVariant="Default">
             <!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
    <Application.Styles>
	       <FluentTheme />
    </Application.Styles>
</Application>

6、App.axaml.cs

csharp 复制代码
<Application xmlns="https://github.com/avaloniaui"
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;

using AvaRea.ViewModels;
using AvaRea.Views;

namespace AvaRea;

public partial class App : Application
{
    public override void Initialize()
    {
        AvaloniaXamlLoader.Load(this);
    }

    public override void OnFrameworkInitializationCompleted()
    {
        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
        {
            desktop.MainWindow = new MainView
            {
                DataContext = new MainViewModel()
            };
        }
        else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
        {
            singleViewPlatform.MainView = new MainView
            {
                DataContext = new MainViewModel()
            };
        }

        base.OnFrameworkInitializationCompleted();
    }
}

7、Program.cs

csharp 复制代码
using System;

using Avalonia;
using Avalonia.ReactiveUI;

namespace AvaRea.Desktop;

class Program
{
    // Initialization code. Don't use any Avalonia, third-party APIs or any
    // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
    // yet and stuff might break.
    [STAThread]
    public static void Main(string[] args) => BuildAvaloniaApp()
        .StartWithClassicDesktopLifetime(args);

    // Avalonia configuration, don't remove; also used by visual designer.
    public static AppBuilder BuildAvaloniaApp()
        => AppBuilder.Configure<App>()
            .UsePlatformDetect()
            .WithInterFont()
            .LogToTrace()
            .UseReactiveUI();
}

总结

Avalonia 给你跨平台的舞台,ReactiveUI 给你响应式的灵魂,Source Generators 给你自动生成代码;三者合体 = 用最少的代码,写出最快、最稳、最易维护的跨平台 .NET UI。

相关推荐
心疼你的一切3 小时前
使用Unity引擎开发Rokid主机应用的模型交互操作
游戏·ui·unity·c#·游戏引擎·交互
韩立学长3 小时前
【开题答辩实录分享】以《C#大型超市商品上架调配管理系统的设计与实现》为例进行答辩实录分享
开发语言·c#
Alex Gram4 小时前
Avalonia UI 开发核心注意事项:从理念到部署的避坑指南
avalonia
玩泥巴的6 小时前
.NET驾驭Word之力:数据驱动文档 - 邮件合并与自定义数据填充完全指南
c#·word·.net·com互操作
心疼你的一切9 小时前
使用Unity引擎开发Rokid主机应用的全面配置交互操作
学习·游戏·unity·c#·游戏引擎·交互
椒颜皮皮虾྅16 小时前
【DeploySharp 】基于DeploySharp 的深度学习模型部署测试平台:安装和使用流程
人工智能·深度学习·开源·c#·openvino
kalvin_y_liu1 天前
【MES架构师与C#高级工程师(设备控制方向)两大职业路径的技术】
开发语言·职场和发展·c#·mes
椒颜皮皮虾1 天前
基于DeploySharp 的深度学习模型部署测试平台:支持YOLO全系列模型
c#
James.TCG1 天前
Avalonia桌面应用发布到Ubuntu22.04
linux·ubuntu·avalonia