
рдЖрдзреБрдирд┐рдХ рдЙрджреНрдпрдо рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлреЗрд╕ рдХрд╛рдлреА рдЬрдЯрд┐рд▓ рд╣реИрдВред рдЖрдк, рдПрдХ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдЕрдХреНрд╕рд░ рдЗрди-рдРрдк рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдирдкреБрдЯ рдХреЛ рдорд╛рдиреНрдп рдХрд░рдиреЗ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд░реАрдпрддрд╛рдУрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕реНрдХреНрд░реАрди рджрд┐рдЦрд╛рдиреЗ рдпрд╛ рдЫрд┐рдкрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдмреЗрд╣рддрд░ UX рдХреЗ рд▓рд┐рдП, рдЖрдкрдХрд╛ рдРрдк рдбрд┐рд╕реНрдХ рдХреЛ рд╕реНрдЯреЗрдЯ рдХреЛ рд╕реЗрд╡ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрдм рдРрдк рд╕рд╕реНрдкреЗрдВрдб рд╣реЛ рд░рд╣рд╛ рд╣реЛ рдФрд░ рдРрдк рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдкрд░ рд╕реНрдЯреЗрдЯ рдХреЛ рд░рд┐рд╕реНрдЯреЛрд░ рдХрд░ рд░рд╣рд╛ рд╣реЛред
рдЬрдм рдРрдк рдмрдВрдж рд╣реЛ рд░рд╣рд╛ рд╣реЛ рдпрд╛ рдирд┐рд▓рдВрдмрд┐рдд рд╣реЛ рд░рд╣рд╛ рд╣реЛ, рддрдм рд░рд┐рдПрдХреНрдЯрд┐рд╡рд┐рд╡ рдЖрдкрдХреЛ рд╡реНрдпреВ рдореЙрдбрд▓ рдЯреНрд░реА рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рдХреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реНрдЯреЗрдЯ рдХреЛ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреА рд╕реБрд╡рд┐рдзрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдкреНрд░рддрд┐ рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдкрд░ рд╕рд╕реНрдкреЗрдВрд╢рди рдХреА рдШрдЯрдирд╛рдПрдВ рдмрджрд▓рддреА рд░рд╣рддреА рд╣реИрдВред ReactiveUI WPF рдХреЗ рд▓рд┐рдП Exit
рдЗрд╡реЗрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, DidEnterBackground
рд▓рд┐рдП рдПрдХреНрдЯрд┐рд╡рд┐рдЯреАрдкреЙрдиреНрдб рдХрд┐рдпрд╛редрдПрдВрдбреНрд░реЙрдпрдб, DidEnterBackground
рд▓рд┐рдП DidEnterBackground, UWP рдХреЗ рд▓рд┐рдП OnLaunched
ред
рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ рд╣рдо рдПрдХ рдирдореВрдирд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ рдЬреЛ рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдХреЗ рд╕рд╛рде рд░рд┐рдПрдХреНрдЯрд┐рд╡рд┐рд╡реНрдпреВ рд╕рд╕реНрдкреЗрдВрд╢рди рдлрд╝реАрдЪрд░ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ - рдПрдХ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо .NET рдХреЛрд░ XAML- рдЖрдзрд╛рд░рд┐рдд GUI рдлреНрд░реЗрдорд╡рд░реНрдХред рдЗрд╕ рдиреЛрдЯ рдХреЛ рдкрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЖрдкрдХреЛ MVVM рдкреИрдЯрд░реНрди рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд╕рд╛рде рдкрд░рд┐рдЪрд┐рдд рд╣реЛрдиреЗ рдХреА рдЙрдореНрдореАрдж рд╣реИред рдпрджрд┐ рдЖрдк рд╡рд┐рдВрдбреЛрдЬ 10 рдпрд╛ рдЙрдмрдВрдЯреВ 18 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдЪрд░рдгреЛрдВ рдХреЛ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЪрд▓реЛ рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдУ!
рдмреВрдЯрд╕реНрдЯреНрд░реИрдкрд┐рдВрдЧ рдкреНрд░реЛрдЬреЗрдХреНрдЯ
рд░рд┐рдПрдХреНрдЯрд┐рд╡рдпреВрдЖрдИ рдХреЛ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдирдпрд╛ .NET рдХреЛрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рддреЗ рд╣реИрдВред рддрдм рд╣рдо Avalonia.ReactiveUI
рдкреИрдХреЗрдЬ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдкреИрдХреЗрдЬ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдЬреАрд╡рди рдЪрдХреНрд░ рд╣реБрдХ, рд░реВрдЯрд┐рдВрдЧ рдФрд░ рд╕рдХреНрд░рд┐рдпрдг рдЕрд╡рд╕рдВрд░рдЪрдирд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред .NET рдХреЛрд░ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдФрд░ рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЖрджреЗрд╢реЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдпрд╛рдж рд░рдЦреЗрдВред
git clone https://github.com/AvaloniaUI/avalonia-dotnet-templates git --git-dir ./avalonia-dotnet-templates/.git checkout 9263c6b dotnet new --install ./avalonia-dotnet-templates dotnet new avalonia.app -o ReactiveUI.Samples.Suspension cd ./ReactiveUI.Samples.Suspension dotnet add package Avalonia.ReactiveUI dotnet add package Avalonia.Desktop dotnet add package Avalonia
рдЪрд▓реЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪрд▓рд╛рддреЗ рд╣реИрдВ рдФрд░ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ "рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИ" рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ!
# Use .NET Core version which you have installed. # It can be netcoreapp2.0, netcoreapp2.1 and so on. dotnet run --framework netcoreapp3.0

MyGet рд╕реЗ Avalonia рдкреНрд░реАрд╡реНрдпреВ рдмрд┐рд▓реНрдб рдХреА рд╕реНрдерд╛рдкрдирд╛
рдирд╡реАрдирддрдо рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдкреИрдХреЗрдЬ рдХреЛ MyGet рдкрд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рд░ рдмрд╛рд░ рдПрдХ рдирдИ рдкреНрд░рддрд┐рдмрджреНрдзрддрд╛ GitHub рдкрд░ рдПрд╡рд▓реЛрдирд┐рдпрд╛ рднрдВрдбрд╛рд░ рдХреА master
рд╢рд╛рдЦрд╛ рдХреЛ рдзрдХреЗрд▓ рджреА рдЬрд╛рддреА рд╣реИред рд╣рдорд╛рд░реЗ рдРрдк рдореЗрдВ MyGet рдХреЗ рдирд╡реАрдирддрдо рдкреИрдХреЗрдЬреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ nuget.config
рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо .NET рдХреЛрд░ CLI рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдкрд╣рд▓реЗ рдмрдирд╛рдИ рдЧрдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ sln
рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ:
dotnet new sln # Ctrl+C dotnet sln ReactiveUI.Samples.Suspension.sln add ReactiveUI.Samples.Suspension.csproj
рдЕрдм рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде nuget.config
рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ:
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <add key="AvaloniaCI" value="https://www.myget.org/F/avalonia-ci/api/v2" /> </packageSources> </configuration>
рдЖрдорддреМрд░ рдкрд░, рдирдП рдЬреЛрдбрд╝реЗ рдЧрдП MyGet рдлрд╝реАрдб рд╕реЗ рдкреИрдХреЗрдЬреЛрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реА IDE рдХреЛ рдмрд╛рдзреНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреБрдирд░рд╛рд░рдВрдн рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдорд╛рдзрд╛рди рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдорджрдж рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред рдлрд┐рд░, рд╣рдо рдиреНрдпреВрдЧреЗрдЯ рдкреИрдХреЗрдЬ рдореИрдиреЗрдЬрд░ рдЬреАрдпреВрдЖрдИ, рдпрд╛ .NET рдХреЛрд░ рд╕реАрдПрд▓рдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрд╡рд▓реЛрдирд┐рдпрд╛ рдкреИрдХреЗрдЬ рдХреЛ рд╕рдмрд╕реЗ рд╣рд╛рд▓ рдХреЗ рд╕рдВрд╕реНрдХрд░рдг (рдпрд╛ рдХрдо рд╕реЗ рдХрдо 0.9.1
) рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд░рддреЗ рд╣реИрдВ:
dotnet add package Avalonia.ReactiveUI --version 0.9.1 dotnet add package Avalonia.Desktop --version 0.9.1 dotnet add package Avalonia --version 0.9.1 cat ReactiveUI.Samples.Suspension.csproj
ReactiveUI.Samples.Suspension.csproj
рдлрд╝рд╛рдЗрд▓ рдХреЛ рдХреБрдЫ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> </PropertyGroup> <ItemGroup> <Compile Update="**\*.xaml.cs"> <DependentUpon>%(Filename)</DependentUpon> </Compile> <AvaloniaResource Include="**\*.xaml"> <SubType>Designer</SubType> </AvaloniaResource> </ItemGroup> <ItemGroup> <PackageReference Include="Avalonia" Version="0.9.1" /> <PackageReference Include="Avalonia.Desktop" Version="0.9.1" /> <PackageReference Include="Avalonia.ReactiveUI" Version="0.9.1" /> </ItemGroup> </Project>
рд╣рдо рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд░реВрдЯ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдХреЗ рдЕрдВрджрд░ рджреЛ рдирдП рдлреЛрд▓реНрдбрд░ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬрд┐рдиреНрд╣реЗрдВ рдХреНрд░рдорд╢рдГ Views/
рдФрд░ ViewModels/
рдирд╛рдо рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо MainWindow
рдХреНрд▓рд╛рд╕ рдХрд╛ рдирд╛рдо рдмрджрд▓рдХрд░ MainView
рдХрд░ MainView
рдФрд░ рдЗрд╕реЗ Views/
folder рдореЗрдВ рд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВред рд╕рдВрдмрдВрдзрд┐рдд XAML рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рдВрдкрд╛рджрд┐рдд рд╡рд░реНрдЧ рдХреЗ рд╕рдВрджрд░реНрднреЛрдВ рдХрд╛ рдирд╛рдо рдмрджрд▓рдирд╛ рдпрд╛рдж рд░рдЦреЗрдВ, рдЕрдиреНрдпрдерд╛, рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕рдВрдХрд▓рд┐рдд рдирд╣реАрдВ рд╣реЛрдЧреАред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, MainView
рд▓рд┐рдП рдирд╛рдо рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╛рдж рд░рдЦреЗрдВ ReactiveUI.Samples.Suspension.Views
рд╕реНрдерд┐рд░рддрд╛ рдХреЗ рд▓рд┐рдПред рдлрд┐рд░, рд╣рдо рджреЛ рдЕрдиреНрдп рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, Program.cs
рдФрд░ App.xaml.cs
рд╣рдо UseReactiveUI
рдРрдк рдмрд┐рд▓реНрдбрд░ рдХреЗ рд▓рд┐рдП UseReactiveUI
рд▓рд┐рдП рдПрдХ рдХреЙрд▓ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдРрдк рдЗрдиреАрд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЛрдб рдХреЛ OnFrameworkInitializationCompleted
рд╕реЗ OnFrameworkInitializationCompleted
ред OnFrameworkInitializationCompleted
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЖрдЬреАрд╡рди рдкреНрд░рдмрдВрдзрди рджрд┐рд╢рд╛рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдЕрдиреБрд░реВрдк рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐:
Program.cs
class Program {
App.xaml.cs
public class App : Application { public override void Initialize() => AvaloniaXamlLoader.Load(this);
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд╕реБрдирд┐рд╢реНрдЪрд┐рдд using Avalonia.ReactiveUI
рдХрд╛ using Avalonia.ReactiveUI
Program.cs
рдлрд╝рд╛рдЗрд▓ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реА IDE рдиреЗ рдкрд╣рд▓реЗ рд╣реА рдЙрд╕ рдирд╛рдо рд╕реНрдерд╛рди рдХреЛ рдЖрдпрд╛рдд рдХрд░ рд▓рд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реБрдЖ, рддреЛ рд╣рдореЗрдВ рдПрдХ рд╕рдВрдХрд▓рди-рд╕рдордп рддреНрд░реБрдЯрд┐ рдорд┐рд▓реЗрдЧреАред рдЕрдВрдд рдореЗрдВ, рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИ рдХрд┐ рдРрдк рдПрдХ рдирдИ рд╡рд┐рдВрдбреЛ рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЪрд▓рд╛рддрд╛ рд╣реИ рдФрд░ рджрд┐рдЦрд╛рддрд╛ рд╣реИ:
dotnet run --framework netcoreapp2.1

рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо .NET рдРрдк рдореЗрдВ рдЗрди-рдРрдк рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЗ рдЖрдпреЛрдЬрди рдХреЗ рджреЛ рд╕рд╛рдорд╛рдиреНрдп рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИрдВ - рджреГрд╢реНрдп-рдкреНрд░рдердо рдФрд░ рджреГрд╢реНрдп рдореЙрдбрд▓-рдкреНрд░рдердоред рдкреВрд░реНрд╡ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдорд╛рдирддрд╛ рд╣реИ рдХрд┐ рджреГрд╢реНрдп рдкрд░рдд рдиреЗрд╡рд┐рдЧреЗрд╢рди рд╕реНрдЯреИрдХ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рддреА рд╣реИ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдлрд╝реНрд░реЗрдо рдФрд░ рдкреГрд╖реНрда рдХрдХреНрд╖рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗред рдмрд╛рдж рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде, рджреГрд╢реНрдп рдореЙрдбрд▓ рдкрд░рдд рдПрдХ рдордВрдЪ-рдЕрдЬреНрдЮреЗрдп рдЕрдореВрд░реНрдд рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХрд╛ рдЦреНрдпрд╛рд▓ рд░рдЦрддрд╛ рд╣реИред ReactiveUI рдЯреВрд▓реАрдВрдЧ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рдореЙрдбрд▓-рдкреНрд░рдердо рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред ReactiveUI рд░реВрдЯрд┐рдВрдЧ рдореЗрдВ рдПрдХ IScreen
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд░реВрдЯрд┐рдВрдЧ рдЕрд╡рд╕реНрдерд╛, рдХрдИ IRoutableViewModel
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдФрд░ рдПрдХ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╡рд┐рд╢рд┐рд╖реНрдЯ XAML рдирд┐рдпрдВрддреНрд░рдг рд╣реЛрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ RoutedViewHost
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред

RoutingState
рдСрдмреНрдЬреЗрдХреНрдЯ рдиреЗрд╡рд┐рдЧреЗрд╢рди рд╕реНрдЯреИрдХ рдкреНрд░рдмрдВрдзрди рдХреЛ RoutingState
рдХрд░рддрд╛ рд╣реИред IScreen
рдиреЗрд╡рд┐рдЧреЗрд╢рди рд░реВрдЯ рд╣реИ, рд▓реЗрдХрд┐рди рдирд╛рдо рдХреЗ рдмрд╛рд╡рдЬреВрдж, рдЗрд╕реЗ рдкреВрд░реА рд╕реНрдХреНрд░реАрди рдкрд░ рдХрдмреНрдЬрд╛ рдирд╣реАрдВ рдХрд░рдирд╛ рд╣реИред RoutedViewHost
рдмрд╛рдзреНрдп RoutingState
рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЪрдпрдирд┐рдд IRoutableViewModel
рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рджреГрд╢реНрдп рдПрдореНрдмреЗрдб рдХрд░рддрд╛ рд╣реИред рд╡рд░реНрдгрд┐рдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдмрд╛рдж рдореЗрдВ рдЕрдзрд┐рдХ рд╡реНрдпрд╛рдкрдХ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рдЪрд┐рддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рд╕реНрдерд╛рдпреА рджреГрд╢реНрдп рдореЙрдбрд▓ рд╕реНрдерд┐рддрд┐
рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдЦреЛрдЬ рд╕реНрдХреНрд░реАрди рджреГрд╢реНрдп рдореЙрдбрд▓ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред

рд╣рдо рдпрд╣ рддрдп рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдВрдж рд╣реЛрдиреЗ рд╕реЗ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреМрди рд╕реЗ рд╡реНрдпреВ рдореЙрдбрд▓ рдХреЗ рдХреМрди рд╕реЗ рдЧреБрдг рд╣реИрдВ рдФрд░ рдХрд┐рди рд▓реЛрдЧреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдирд╛ рд╣реИред рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдХрдорд╛рдВрдб рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ рдЬреЛ ICommand
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред ReactiveCommand<TIn, TOut>
рд╡рд░реНрдЧ рдХреЛ рдЖрдорддреМрд░ рдкрд░ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рдХрд╛ CanExecute
рдЗрдВрдбрд┐рдХреЗрдЯрд░ рдЖрдорддреМрд░ рдкрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдореЙрдбрд▓ рдХреЗ рдЧреБрдгреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╣рд░ рдмрд╛рд░ рдЙрди рдЧреБрдгреЛрдВ рдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рднреА рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рдмрд╛рдж ReactiveCommand<TIn, TOut>
рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдЦреЛрдЬ рдкрд░рд┐рдгрд╛рдо рд░рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдпрд╣ рдмрд╣рд╕ рдХрд╛ рд╡рд┐рд╖рдп рд╣реИ, рд▓реЗрдХрд┐рди рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдХреЛ рд╕рд╣реЗрдЬрдирд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИред
ViewModels / SearchViewModel.cs
[DataContract] public class SearchViewModel : ReactiveObject, IRoutableViewModel { private readonly ReactiveCommand<Unit, Unit> _search; private string _searchQuery;
рд╣рдо [DataContract]
рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рд╕рдВрдкреВрд░реНрдг рджреГрд╢реНрдп рдореЙрдбрд▓ рд╡рд░реНрдЧ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рдХреЛ рдПрдиреЛрдЯреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдо [DataMember]
рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рдХреНрд░рдордмрджреНрдз рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред рдпрд╣ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рдЕрдЧрд░ рд╣рдо рдСрдкреНрдЯ-рдЗрди рдХреНрд░рдорд╛рдВрдХрди рдореЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред рдХреНрд░рдордмрджреНрдзрддрд╛ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП, рдСрдкреНрдЯ-рдЖрдЙрдЯ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╕рднреА рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреНрд╖реЗрддреНрд░реЛрдВ рдФрд░ рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрдм рддрдХ рдХрд┐ рдЖрдк [IgnoreDataMember]
рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд╕рд╛рде рдПрдиреЛрдЯреЗрдЯ рдХрд░рдХреЗ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЙрдиреНрд╣реЗрдВ рдЕрдирджреЗрдЦрд╛ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдСрдкреНрдЯ-рдЗрди рдХрд╛ рдорддрд▓рдм рд╡рд┐рдкрд░реАрдд рд╣реИред рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд, рд╣рдо рдЕрдкрдиреЗ рджреГрд╢реНрдп рдореЙрдбрд▓ рд╡рд░реНрдЧ рдореЗрдВ IRoutableViewModel
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬрдм рд╣рдо рдиреЗрд╡рд┐рдЧреЗрд╢рди рд╕реНрдЯреИрдХ рдХреЗ рдПрдХ рднрд╛рдЧ рдХреЗ рд░реВрдк рдореЗрдВ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред
рд▓реЙрдЧрд┐рди рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдгViewModels / LoginViewModel.cs
[DataContract] public class LoginViewModel : ReactiveObject, IRoutableViewModel { private readonly ReactiveCommand<Unit, Unit> _login; private string _password; private string _username;
рджреЛ рджреГрд╢реНрдп рдореЙрдбрд▓ IRoutableViewModel
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдиреЗрд╡рд┐рдЧреЗрд╢рди рд╕реНрдХреНрд░реАрди рдореЗрдВ рдПрдореНрдмреЗрдбреЗрдб рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВред рдЕрдм IScreen
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИред рдлрд┐рд░, рд╣рдо [DataContract]
рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдХрд┐рди рднрд╛рдЧреЛрдВ рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рдирд╛ рд╣реИ рдФрд░ рдХрд┐рди рд▓реЛрдЧреЛрдВ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рдирд╛ рд╣реИред рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, RoutingState
рдкреНрд░реЙрдкрд░реНрдЯреА рд╕реЗрдЯрд░ рдХреЛ рдЬрд╛рдирдмреВрдЭрдХрд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ - рдпрд╣ рд╣рдорд╛рд░реЗ рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рдХреЛ рд╕рдВрдкрддреНрддрд┐ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬрдм рд╡рд╣ RoutingState
рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
ViewModels / MainViewModel.cs
[DataContract] public class MainViewModel : ReactiveObject, IScreen { private readonly ReactiveCommand<Unit, Unit> _search; private readonly ReactiveCommand<Unit, Unit> _login; private RoutingState _router = new RoutingState(); public MainViewModel() {
рд╣рдорд╛рд░реЗ рдореБрдЦреНрдп рджреГрд╢реНрдп рдореЙрдбрд▓ рдореЗрдВ, рд╣рдо рдбрд┐рд╕реНрдХ рдкрд░ рдХреЗрд╡рд▓ рдПрдХ рдлрд╝реАрд▓реНрдб рдХреЛ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВ - рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ RoutingState
ред рд╣рдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдЖрджреЗрд╢реЛрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдирдХреА рдЙрдкрд▓рдмреНрдзрддрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд░рд╛рдЙрдЯрд░ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреА рд╣реИред рд░рд╛рдЙрдЯрд░ рдХреЛ рдЙрд╕реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдЬрдм рд╣рдо рд░рд╛рдЙрдЯрд░ рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рддреЗ рд╕рдордп рд╣рдорд╛рд░реЗ IRoutableViewModel
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдирдХрд╛рд░реА рд╢рд╛рдорд┐рд▓ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдмрд╛рдж рдореЗрдВ рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Newtonsoft.Json рдХреА TypenameHandling.All
рд╕реЗрдЯрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рд╣рдо ViewModels/
рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ MainViewModel
, ReactiveUI.Samples.Suspension.ViewModels
рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдирд╛рдо рд╕реНрдерд╛рди рд╕рдорд╛рдпреЛрдЬрд┐рдд рдХрд░рддреЗ рд╣реИрдВред

рдПрдХ Avalonia рдРрдк рдореЗрдВ рд░реВрдЯрд┐рдВрдЧ
рдлрд┐рд▓рд╣рд╛рд▓, рд╣рдордиреЗ рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдкреНрд░реЗрдЬреЗрдВрдЯреЗрд╢рди рдореЙрдбрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рджрд┐рдпрд╛ рд╣реИред рдмрд╛рдж рдореЗрдВ, рдПрдХ рдЕрд▓рдЧ рдЕрд╕реЗрдВрдмрд▓реА рдЯрд╛рд░рдЧреЗрдЯрд┐рдВрдЧ .NET рд╕реНрдЯреИрдВрдбрд░реНрдб рдореЗрдВ рд╡реНрдпреВ рдореЙрдбрд▓ рдХреНрд▓рд╛рд╕реЗрд╕ рдХреЛ рдирд┐рдХрд╛рд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдРрдк рдХреЗ рдореБрдЦреНрдп рднрд╛рдЧ рдХреЛ рдХрдИ .NET GUI рдлреНрд░реЗрдорд╡рд░реНрдХ рдореЗрдВ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЕрдм рдпрд╣ рд╣рдорд╛рд░реЗ рдРрдк рдХреЗ рдПрд╡рд▓реЛрдирд┐рдпрд╛-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЬреАрдпреВрдЖрдИ рднрд╛рдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рд╣рдо рдХреНрд░рдорд╢рдГ SearchView.xaml
рдФрд░ SearchView.xaml.cs
рдирд╛рдо рдХреЗ Views/
рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рджреЛ рдлрд╛рдЗрд▓реЗрдВ рдмрдирд╛рддреЗ рд╣реИрдВред рдпреЗ рдПрдХрд▓ рдЦреЛрдЬ рджреГрд╢реНрдп рдХреЗ рджреЛ рднрд╛рдЧ рд╣реИрдВ - рдкреВрд░реНрд╡ рд╡рд╛рд▓рд╛ UI XAML рдореЗрдВ рдШреЛрд╖рд┐рдд рд░реВрдк рд╕реЗ рд╡рд░реНрдгрд┐рдд рд╣реИ, рдФрд░ рдмрд╛рдж рд╡рд╛рд▓реЗ рдореЗрдВ C # рдХреЛрдб-рдкреАрдЫреЗ рд╣реИред рдпрд╣ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдкрд╣рд▓реЗ рдмрдирд╛рдП рдЧрдП рдЦреЛрдЬ рджреГрд╢реНрдп рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рджреГрд╢реНрдп рд╣реИред
рдЕрд╡рд▓реЛрдирд┐рдпрд╛ рдореЗрдВ рдкреНрд░рдпреБрдХреНрдд XAML рдмреЛрд▓реА рдХреЛ WPF, UWP рдпрд╛ XF рд╕реЗ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рддреБрд░рдВрдд рдкрд░рд┐рдЪрд┐рдд рдорд╣рд╕реВрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдКрдкрд░ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╣рдо рдПрдХ рд╕рд░рд▓ рд▓реЗрдЖрдЙрдЯ рдмрдирд╛рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рдЯреЗрдХреНрд╕реНрдЯ рдмреЙрдХреНрд╕ рдФрд░ рдПрдХ рдмрдЯрди рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдЦреЛрдЬ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИред рд╣рдо SearchViewModel
рд╕реЗ рдЧреБрдг рдФрд░ рдЖрджреЗрд╢ рдХреЛ SearchViewModel
рдореЗрдВ рдШреЛрд╖рд┐рдд рдирд┐рдпрдВрддреНрд░рдгреЛрдВ рд╕реЗ SearchView
ред
рджреГрд╢реНрдп / SearchView.xaml
<UserControl xmlns="https://github.com/avaloniaui" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DataContext="{d:DesignInstance viewModels:SearchViewModel}" xmlns:viewModels="clr-namespace:ReactiveUI.Samples.Suspension.ViewModels" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="ReactiveUI.Samples.Suspension.Views.SearchView" xmlns:reactiveUi="http://reactiveui.net" mc:Ignorable="d"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="48" /> <RowDefinition Height="48" /> <RowDefinition Height="48" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Text="Search view" Margin="5" /> <TextBox Grid.Row="1" Text="{Binding SearchQuery, Mode=TwoWay}" /> <Button Grid.Row="2" Content="Search" Command="{Binding Search}" /> </Grid> </UserControl>
рджреГрд╢реНрдп / SearchView.xaml.cs
public sealed class SearchView : ReactiveUserControl<SearchViewModel> { public SearchView() {
WPF рдФрд░ UWP рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ SearchView.xaml
рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП рдХреЛрдб-рдкреАрдЫреЗ рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИред рдЬрдм рд╕рдХреНрд░рд┐рдпрдг рддрд░реНрдХ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП WhenActivated
рдХреЙрд▓ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред WhenActivated
рд▓рд┐рдП рдкрд╣рд▓реА рджрд▓реАрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдбрд┐рд╕реНрдкреЛрдЬреЗрдмрд▓ рдХрд╛ рдирд┐рдкрдЯрд╛рди рддрдм рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рджреГрд╢реНрдп рдирд┐рд╖реНрдХреНрд░рд┐рдп рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдкрдХрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЧрд░реНрдо рд╡реЗрдзрд╢рд╛рд▓рд╛рдУрдВ (рдЬреИрд╕реЗ рд╕реНрдерд┐рддрд┐ рд╕реЗрд╡рд╛рдУрдВ, рдЯрд╛рдЗрдорд░, рдИрд╡реЗрдВрдЯ рдПрдЧреНрд░реАрдЧреЗрдЯрд░реНрд╕) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИ, рддреЛ рдПрдХ DisposeWith
рдХреЙрд▓ рдЬреЛрдбрд╝рдХрд░ WhenActivated
рд╕рдордЧреНрд░ рдбрд┐рд╕реНрдкреЛрдЬреЗрдмрд▓ рдХреЗ рд▓рд┐рдП рд╕рджрд╕реНрдпрддрд╛ рд╕рдВрд▓рдЧреНрди рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдмреБрджреНрдзрд┐рдорд╛рди рдирд┐рд░реНрдгрдп рд╣реЛрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдпрд╣ рджреГрд╢реНрдп рдЙрди рд╣реЙрдЯ DisposeWith
рд╕реЗ рдЕрд▓рдЧ рд╣реЛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдореЗрдореЛрд░реА рд▓реАрдХ рдирд╣реАрдВ рд╣реЛрдЧреАред
рд▓реЙрдЧрд┐рди рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдгрджреГрд╢реНрдп / LoginView.xaml
<UserControl xmlns="https://github.com/avaloniaui" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DataContext="{d:DesignInstance viewModels:LoginViewModel, IsDesignTimeCreatable=True}" xmlns:viewModels="clr-namespace:ReactiveUI.Samples.Suspension.ViewModels" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="ReactiveUI.Samples.Suspension.Views.LoginView" xmlns:reactiveUi="http://reactiveui.net" mc:Ignorable="d"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="48" /> <RowDefinition Height="48" /> <RowDefinition Height="48" /> <RowDefinition Height="48" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Text="Login view" Margin="5" /> <TextBox Grid.Row="1" Text="{Binding Username, Mode=TwoWay}" /> <TextBox Grid.Row="2" PasswordChar="*" Text="{Binding Password, Mode=TwoWay}" /> <Button Grid.Row="3" Content="Login" Command="{Binding Login}" /> </Grid> </UserControl>
рджреГрд╢реНрдп / LoginView.xaml.cs
public sealed class LoginView : ReactiveUserControl<LoginViewModel> { public LoginView() { this.WhenActivated(disposables => { }); AvaloniaXamlLoader.Load(this); } }
рд╣рдо Views/MainView.xaml
рдФрд░ Views/MainView.xaml.cs
рдлрд╝рд╛рдЗрд▓реЗрдВ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдореБрдЦреНрдп рд╡рд┐рдВрдбреЛ XAML рд▓реЗрдЖрдЙрдЯ рдореЗрдВ Avalonia.ReactiveUI
рдирд╛рдорд╕реНрдерд╛рди рд╕реЗ RoutedViewHost
рдирд┐рдпрдВрддреНрд░рдг рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдФрд░ RoutedViewHost
рдХреЗ Router
MainViewModel
рдХреЛ RoutedViewHost.Router
рдЧреБрдг рд╕реЗ RoutedViewHost.Router
рд╣реИрдВред рд╣рдо рджреЛ рдмрдЯрди рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдПрдХ рдЦреЛрдЬ рдкреГрд╖реНрда рдЦреЛрд▓рддрд╛ рд╣реИ рдФрд░ рджреВрд╕рд░рд╛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдкреГрд╖реНрда рдЦреЛрд▓рддрд╛ рд╣реИред
рджреГрд╢реНрдп / MainView.xaml
<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="450" x:Class="ReactiveUI.Samples.Suspension.Views.MainView" xmlns:reactiveUi="http://reactiveui.net" Title="ReactiveUI.Samples.Suspension"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="48" /> </Grid.RowDefinitions> <reactiveUi:RoutedViewHost Grid.Row="0" Router="{Binding Router}"> <reactiveUi:RoutedViewHost.DefaultContent> <TextBlock Text="Default Content" /> </reactiveUi:RoutedViewHost.DefaultContent> </reactiveUi:RoutedViewHost> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Button Grid.Column="0" Command="{Binding Search}" Content="Search" /> <Button Grid.Column="1" Command="{Binding Login}" Content="Login" /> <Button Grid.Column="2" Command="{Binding Router.NavigateBack}" Content="Back" /> </Grid> </Grid> </Window>
рджреГрд╢реНрдп / MainView.xaml.cs
public sealed class MainView : ReactiveWindow<MainViewModel> { public MainView() { this.WhenActivated(disposables => { }); AvaloniaXamlLoader.Load(this); } }
рдПрдХ рд╕рд░рд▓ рдЕрд╡рд▓реЛрдирд┐рдпрд╛ рдФрд░ рд░рд┐рдПрдХреНрдЯрд┐рд╡реБрдИ рд░реВрдЯрд┐рдВрдЧ рдбреЗрдореЛ рдРрдк рдЕрдм рддреИрдпрд╛рд░ рд╣реИред рдЬрдм рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЦреЛрдЬ рдпрд╛ рд▓реЙрдЧрд┐рди рдмрдЯрди рджрдмрд╛рддрд╛ рд╣реИ, рддреЛ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ рдХрдорд╛рдВрдб рдХреЛ рдЖрдордВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ RoutingState
рдЕрдкрдбреЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред RoutedViewHost
XAML рдирд┐рдпрдВрддреНрд░рдг рд░реВрдЯрд┐рдВрдЧ рд╕реНрдерд┐рддрд┐ рдХреЛ рджреЗрдЦрддрд╛ рд╣реИ, IViewFor<TViewModel>
рд╕реЗ рдЙрдкрдпреБрдХреНрдд IViewFor<TViewModel>
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдПрдХ IViewFor<TViewModel>
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрдВрдЬреАрдХреГрдд рд╣реИ, рддреЛ рдирд┐рдпрдВрддреНрд░рдг рдХрд╛ рдПрдХ рдирдпрд╛ рдЙрджрд╛рд╣рд░рдг IViewFor<TViewModel>
рд╡рд┐рдВрдбреЛ рдореЗрдВ рдмрдирд╛рдпрд╛ рдФрд░ рдПрдореНрдмреЗрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рд╣рдо Locator.CurrentMutable
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ App.OnFrameworkInitializationCompleted
рд╡рд┐рдзрд┐ рдореЗрдВ рд╣рдорд╛рд░реЗ IViewFor
рдФрд░ IScreen
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддреЗ рд╣реИрдВред IViewFor
рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП RoutedViewHost
рдирд┐рдпрдВрддреНрд░рдг рдХреЗ рд▓рд┐рдП IViewFor
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред IScreen
рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд░рдиреЗ рд╕реЗ рд╣рдорд╛рд░реЗ SearchViewModel
рдФрд░ LoginViewModel
рдХреЛ LoginViewModel
рджреМрд░рд╛рди рдкреНрд░реЙрдкрд░реНрдЯреА рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ LoginViewModel
рд╣реИ, рдЬреЛ рдХрд┐ рдкреИрд░рд╛рдореАрдЯрд░ рд░рд╣рд┐рдд рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
App.xaml.cs
public override void OnFrameworkInitializationCompleted() {
рдЖрдЗрдП рд╣рдорд╛рд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░реЗрдВ рдФрд░ рд░рд╛рдЙрдЯрд┐рдВрдЧ рдкреНрд░рджрд░реНрд╢рди рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдпрд╣ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ XAML UI рдорд╛рд░реНрдХрдЕрдк рдХреЗ рд╕рд╛рде рдХреБрдЫ рдЧрд▓рдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ Avalonia XamlIl рдХрдВрдкрд╛рдЗрд▓рд░ рд╣рдореЗрдВ рдХрдВрдкрд╛рдЙрдВрдб рд╕рдордп рдкрд░ рдХрд┐рд╕реА рднреА рддреНрд░реБрдЯрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реВрдЪрд┐рдд рдХрд░реЗрдЧрд╛ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, XamlIl XAML рдбрд┐рдмрдЧрд┐рдВрдЧ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ !
dotnet run --framework netcoreapp3.0

рд╕реЗрд╡рд┐рдВрдЧ рдПрдВрдб рд░рд┐рд╕реНрдЯреЛрд░рд┐рдВрдЧ рдПрдкреНрд▓реАрдХреЗрд╢рди рд╕реНрдЯреЗрдЯ
рдЬрдм рдРрдк рдирд┐рд▓рдВрдмрд┐рдд рдФрд░ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛ рд░рд╣рд╛ рд╣реИ рддреЛ рдРрдк рд╕реНрдЯреЗрдЯ рдХреЛ рдмрдЪрд╛рдиреЗ рдФрд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдирд┐рд▓рдВрдмрди рдЪрд╛рд▓рдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИред рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╡рд┐рд╢рд┐рд╖реНрдЯ AutoSuspendHelper
рд╡рд░реНрдЧ рдЪреАрдЬреЛрдВ рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХрд╛ рдзреНрдпрд╛рди рд░рдЦрддрд╛ рд╣реИ, рдЖрдк, рдПрдХ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдХреЗрд╡рд▓ рдРрдк рдХрдВрдкреЛрдЬрд╝рд┐рд╢рди рд░реВрдЯ рдореЗрдВ рдЗрд╕рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ RxApp.SuspensionHost.CreateNewAppState
рдлреИрдХреНрдЯрд░реА рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдирд╛ RxApp.SuspensionHost.CreateNewAppState
ред рдпрджрд┐ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдХреЛрдИ рд╕рд╣реЗрдЬрд╛ рдЧрдпрд╛ рдбреЗрдЯрд╛ рдирд╣реАрдВ рд╣реИ, рдпрд╛ рдпрджрд┐ рд╕рд╣реЗрдЬрд╛ рдЧрдпрд╛ рдбреЗрдЯрд╛ рджреВрд╖рд┐рдд рд╣реИ, рддреЛ ReactiveUI рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕реНрдерд┐рддрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрд╕ рдлрд╝реИрдХреНрдЯрд░реА рд╡рд┐рдзрд┐ рдХреЛ рдЖрдордВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред
рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо RxApp.SuspensionHost.SetupDefaultSuspendResume
рд╡рд┐рдзрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ ISuspensionDriver
рд▓рд┐рдП ISuspensionDriver
рдХрд╛ рдПрдХ рдирдпрд╛ рдЙрджрд╛рд╣рд░рдг рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рдЖрдЗрдП Newtonsoft.Json рдФрд░ System.IO
рдирд╛рдорд╕реНрдерд╛рди рд╕реЗ рдХрдХреНрд╖рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП ISuspensionDriver
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд╛рдЧреВ рдХрд░реЗрдВред
dotnet add package Newtonsoft.Json
рдбреНрд░рд╛рдЗрд╡рд░ / NewtonsoftJsonSuspensionDriver.cs
public class NewtonsoftJsonSuspensionDriver : ISuspensionDriver { private readonly string _file; private readonly JsonSerializerSettings _settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; public NewtonsoftJsonSuspensionDriver(string file) => _file = file; public IObservable<Unit> InvalidateState() { if (File.Exists(_file)) File.Delete(_file); return Observable.Return(Unit.Default); } public IObservable<object> LoadState() { var lines = File.ReadAllText(_file); var state = JsonConvert.DeserializeObject<object>(lines, _settings); return Observable.Return(state); } public IObservable<Unit> SaveState(object state) { var lines = JsonConvert.SerializeObject(state, _settings); File.WriteAllText(_file, lines); return Observable.Return(Unit.Default); } }
рд╡рд░реНрдгрд┐рдд рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдПрдХ рдЦрд╛рдореА рд╣реИ - рдХреБрдЫ System.IO
рдХрдХреНрд╖рд╛рдПрдВ UWP рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдВрдЧреА, UWP рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реИрдВрдбрдмреЙрдХреНрд╕ рдореЗрдВ рдЪрд▓рддреЗ рд╣реИрдВ рдФрд░ рдЪреАрдЬреЛрдВ рдХреЛ рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╕реЗ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рд╣рд▓ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ - рдЖрдкрдХреЛ UWP рдХреЛ рд▓рдХреНрд╖рд┐рдд рдХрд░рддреЗ рд╕рдордп File
рдФрд░ Directory
рдмрдЬрд╛рдп StorageFile
рдФрд░ StorageFolder
рдХрдХреНрд╖рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдбрд┐рд╕реНрдХ рд╕реЗ рдиреЗрд╡рд┐рдЧреЗрд╢рди рд╕реНрдЯреИрдХ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕рд╕реНрдкреЗрдВрд╢рди рдбреНрд░рд╛рдЗрд╡рд░ рдХреЛ JSON рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рдареЛрд╕ IRoutableViewModel
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд╕рдорд░реНрдерди рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕реАрд▓рд┐рдП рд╣рдо TypeNameHandling.All
Newtonsoft.Json serializer рд╕реЗрдЯрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрдВрдкреЛрдЬрд╝рд┐рд╢рди рд░реВрдЯ рдореЗрдВ рд╕рд╕реНрдкреЗрдВрд╢рди рдбреНрд░рд╛рдЗрд╡рд░ рдХреЛ App.OnFrameworkInitializationCompleted
рд╡рд┐рдзрд┐ рдореЗрдВ App.OnFrameworkInitializationCompleted
рдХрд░рддреЗ рд╣реИрдВ:
public override void OnFrameworkInitializationCompleted() {
Avalonia.ReactiveUI
рдкреИрдХреЗрдЬ рд╕реЗ AutoSuspendHelper
рд╡рд░реНрдЧ рдЖрдкрдХреЗ рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП рдЬреАрд╡рди рдЪрдХреНрд░ рд╣реБрдХ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП ReactiveUI рдлреНрд░реЗрдорд╡рд░реНрдХ рдЗрд╕ рдмрд╛рдд рд╕реЗ рдЕрд╡рдЧрдд рд╣реЛрдЧрд╛ рдХрд┐ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП ISuspensionDriver
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбрд┐рд╕реНрдХ рдкрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реНрдЯреЗрдЯ рдХреЛ рдХрдм рд▓рд┐рдЦрдирд╛ рд╣реИред рд╣рдо рдЕрдкрдирд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдирд┐рд▓рдВрдмрди рдбреНрд░рд╛рдЗрд╡рд░ appstate.json
рдирд╛рдордХ рдПрдХ рдирдИ JSON рдлрд╝рд╛рдЗрд▓ appstate.json
ред рдЬрдм рд╣рдо UI рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рддреЗ рд╣реИрдВ (рдЬреИрд╕реЗ рдХрд┐ рдЯреЗрдХреНрд╕реНрдЯ рдлрд╝реАрд▓реНрдб рдореЗрдВ рдХреБрдЫ рдЯрд╛рдЗрдк рдХрд░реЗрдВ, рдпрд╛ рдХрд┐рд╕реА рднреА рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ) рдФрд░ рдлрд┐рд░ рдРрдк рдХреЛ рдмрдВрдж рдХрд░ рджреЗрдВ, appstate.json
рдлрд╝рд╛рдЗрд▓ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЗ рд╕рдорд╛рди рджрд┐рдЦрд╛рдИ рджреЗрдЧреА:
appstate.jsonрдзреНрдпрд╛рди рджреЗрдВ, рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ JSON рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдпреЛрдЧреНрдп рдирд╛рдо рдХреЗ рд╕рд╛рде $type
рдХреБрдВрдЬреА рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдиреЗрдорд╕реНрдкреЗрд╕ рднреА рд╢рд╛рдорд┐рд▓ рд╣реИред
{ "$type": "ReactiveUI.Samples.Suspension.ViewModels.MainViewModel, ReactiveUI.Samples.Suspension", "Router": { "$type": "ReactiveUI.RoutingState, ReactiveUI", "_navigationStack": { "$type": "System.Collections.ObjectModel.ObservableCollection`1[[ReactiveUI.IRoutableViewModel, ReactiveUI]], System.ObjectModel", "$values": [ { "$type": "ReactiveUI.Samples.Suspension.ViewModels.SearchViewModel, ReactiveUI.Samples.Suspension", "SearchQuery": "funny cats" }, { "$type": "ReactiveUI.Samples.Suspension.ViewModels.LoginViewModel, ReactiveUI.Samples.Suspension", "Username": "worldbeater" } ] } } }
рдпрджрд┐ рдЖрдк рдРрдк рдХреЛ рдмрдВрдж рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓реЙрдиреНрдЪ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рд╕реНрдХреНрд░реАрди рдкрд░ рд╡рд╣реА рд╕рд╛рдордЧреНрд░реА рджрд┐рдЦрд╛рдИ рджреЗрдЧреА рдЬреЛ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рджреЗрдЦреА рд╣реИ! UWP, WPF, Xamarin Forms рдпрд╛ Xamarin рдореВрд▓ рд╕рд╣рд┐рдд, ReactiveUI рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдкреНрд░рддреНрдпреЗрдХ рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдкрд░ рд╡рд░реНрдгрд┐рдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛рдо рдХрд░рддреА рд╣реИред

рдмреЛрдирд╕: ISuspensionDriver
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдЕрдХрд╛рд╡рд╛рдЪреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ - рдПрдХ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ, рд▓рдЧрд╛рддрд╛рд░ рдХреБрдВрдЬреА-рдореВрд▓реНрдп рд╕реНрдЯреЛрд░ред рдпрджрд┐ рдЖрдк рдЕрдкрдиреЗ рдбреЗрдЯрд╛ рдХреЛ UserAccount
рд╕реЗрдХреНрд╢рди рдпрд╛ Secure
рд╕реЗрдХреНрд╢рди рдореЗрдВ рд╕реНрдЯреЛрд░ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ iOS рдФрд░ UWP рдкрд░ рдЖрдкрдХрд╛ рдбреЗрдЯрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдХреНрд▓рд╛рдЙрдб рдкрд░ рдмреИрдХрдЕрдк рд╣реЛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рд╕рднреА рдбрд┐рд╡рд╛рдЗрд╕ рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧрд╛, рдЬрд┐рд╕ рдкрд░ рдРрдк рдЗрдВрд╕реНрдЯреЙрд▓ рд╣реИред рд╕рд╛рде рд╣реА, ReactiveUI.AndroidSupport
рдкреИрдХреЗрдЬ рдореЗрдВ рдПрдХ BundleSuspensionDriver
рдореМрдЬреВрдж рд╣реИред Xamarin.Essentials SecureStorage API рдХрд╛ рдЙрдкрдпреЛрдЧ рдбреЗрдЯрд╛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЖрдк рджреВрд░рд╕реНрде рд╕рд░реНрд╡рд░ рдкрд░ рдпрд╛ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╕реНрд╡рддрдВрддреНрд░ рдХреНрд▓рд╛рдЙрдб рд╕реЗрд╡рд╛ рдореЗрдВ рднреА рдЕрдкрдирд╛ рдРрдк рд╕реНрдЯреЗрдЯ рд╕реНрдЯреЛрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ