目录
[一 设计原型](#一 设计原型)
[二 后台源码](#二 后台源码)
一 设计原型
添加代办事项页面:
二 后台源码
Model:
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 待办事项应用.DataModel
{
public class ToDoItem
{
public string Description { get; set; } = string.Empty;
public bool IsChecked { get; set; }
}
}
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 待办事项应用.DataModel;
namespace 待办事项应用.Services
{
public class ToDoListService
{
public IEnumerable<ToDoItem> GetItems() => new[]
{
new ToDoItem{Description="walk the dog" },
new ToDoItem{Description="buy some milk" },
new ToDoItem{Description="learn avalonia",IsChecked=true }
};
}
}
viewModel:
cs
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Text;
using System.Threading.Tasks;
using 待办事项应用.DataModel;
namespace 待办事项应用.ViewModels
{
public class AddItemViewModel : ViewModelBase
{
private string _description = String.Empty;
public ReactiveCommand<Unit, ToDoItem> OkCommand { get; }
public ReactiveCommand<Unit, Unit> CancelCommand { get; }
public AddItemViewModel()
{
var isValidObservable = this.WhenAnyValue(
x => x.Description,
x => !string.IsNullOrWhiteSpace(x));
OkCommand = ReactiveCommand.Create(
() => new ToDoItem { Description = Description }, isValidObservable);
CancelCommand = ReactiveCommand.Create(() => { });
}
public string Description
{
get => _description;
set => this.RaiseAndSetIfChanged(ref _description, value);
}
}
}
cs
using ReactiveUI;
using System;
using System.Reactive.Linq;
using 待办事项应用.DataModel;
using 待办事项应用.Services;
namespace 待办事项应用.ViewModels
{
public class MainWindowViewModel : ViewModelBase
{
private ViewModelBase _contentViewModel;
// 这个视图模型依赖于 ToDoListService
public MainWindowViewModel()
{
var service = new ToDoListService();
ToDoList = new ToDoListViewModel(service.GetItems());
_contentViewModel = ToDoList;
}
public ViewModelBase ContentViewModel
{
get => _contentViewModel;
private set => this.RaiseAndSetIfChanged(ref _contentViewModel, value);
}
public ToDoListViewModel ToDoList { get; }
public void AddItem()
{
AddItemViewModel addItemViewModel = new();
Observable.Merge(
addItemViewModel.OkCommand,
addItemViewModel.CancelCommand.Select(_ => (ToDoItem?)null))
.Take(1)
.Subscribe( newItem =>
{
if (newItem != null)
{
ToDoList.ListItems.Add(newItem);
}
ContentViewModel = ToDoList;
});
ContentViewModel = addItemViewModel;
}
}
}
cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 待办事项应用.DataModel;
namespace 待办事项应用.ViewModels
{
public class ToDoListViewModel : ViewModelBase
{
public ObservableCollection<ToDoItem> ListItems { get; set; }
public ToDoListViewModel(IEnumerable<ToDoItem> items)
{
ListItems = new ObservableCollection<ToDoItem>(items);
}
}
}
cs
using ReactiveUI;
namespace 待办事项应用.ViewModels
{
public class ViewModelBase : ReactiveObject
{
}
}
View:
cs
<UserControl
x:Class="待办事项应用.Views.AddItemView"
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"
xmlns:vm="using:待办事项应用.ViewModels"
d:DesignHeight="450"
d:DesignWidth="800"
x:DataType="vm:AddItemViewModel"
mc:Ignorable="d">
<DockPanel>
<Button
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
Command="{Binding CancelCommand}"
DockPanel.Dock="Bottom">
Cancel
</Button>
<Button
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
Command="{Binding OkCommand}"
DockPanel.Dock="Bottom">
OK
</Button>
<TextBox
AcceptsReturn="True"
Text="{Binding Description}"
Watermark="Enter your to do item" />
</DockPanel>
</UserControl>
cs
using Avalonia.Controls;
namespace 待办事项应用.Views
{
public partial class AddItemView : UserControl
{
public AddItemView()
{
InitializeComponent();
}
}
}
cs
<Window
x:Class="待办事项应用.Views.MainWindow"
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"
xmlns:views="clr-namespace:待办事项应用.Views"
xmlns:vm="using:待办事项应用.ViewModels"
Title="待办事项应用"
d:DesignHeight="450"
d:DesignWidth="800"
x:DataType="vm:MainWindowViewModel"
Content="{Binding ContentViewModel}"
Icon="/Assets/avalonia-logo.ico"
mc:Ignorable="d" />
cs
using Avalonia.Controls;
namespace 待办事项应用.Views
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
cs
<UserControl
x:Class="待办事项应用.Views.ToDoListView"
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"
xmlns:vm="using:待办事项应用.ViewModels"
d:DesignHeight="450"
d:DesignWidth="800"
x:DataType="vm:ToDoListViewModel"
mc:Ignorable="d">
<DockPanel>
<Button
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
x:CompileBindings="False"
Command="{Binding $parent[Window].DataContext.AddItem}"
DockPanel.Dock="Bottom">
Add Item
</Button>
<ItemsControl ItemsSource="{Binding ListItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox
Margin="4"
Content="{Binding Description}"
IsChecked="{Binding IsChecked}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
</UserControl>
cs
using Avalonia.Controls;
namespace 待办事项应用.Views
{
public partial class ToDoListView : UserControl
{
public ToDoListView()
{
InitializeComponent();
}
}
}
启动引导程序:
cs
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using 待办事项应用.ViewModels;
using 待办事项应用.Views;
namespace 待办事项应用
{
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
};
}
base.OnFrameworkInitializationCompleted();
}
}
}
cs
using Avalonia;
using Avalonia.ReactiveUI;
using System;
namespace 待办事项应用
{
internal sealed 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();
}
}