59 changed files with 4216 additions and 94 deletions
@ -0,0 +1,304 @@ |
|||
# Root-level build output |
|||
bin/ |
|||
obj/ |
|||
publish/ |
|||
|
|||
## Ignore Visual Studio temporary files, build results, and files generated by popular Visual Studio add-ons. |
|||
|
|||
# User-specific files |
|||
*.rsuser |
|||
*.suo |
|||
*.user |
|||
*.userosscache |
|||
*.sln.docstates |
|||
|
|||
# MonoDevelop/Xamarin Studio user-specific files |
|||
*.userprefs |
|||
|
|||
# Build results |
|||
[Dd]ebug/ |
|||
[Dd]ebugPublic/ |
|||
[Rr]elease/ |
|||
[Rr]eleases/ |
|||
x64/ |
|||
x86/ |
|||
[Ww][Ii][Nn]32/ |
|||
[Aa][Rr][Mm]/ |
|||
[Aa][Rr][Mm]64/ |
|||
bld/ |
|||
[Bb]in/ |
|||
[Oo]bj/ |
|||
[Ll]og/ |
|||
[Ll]ogs/ |
|||
|
|||
# Visual Studio 2015/2017 cache/options directory |
|||
.vs/ |
|||
|
|||
# Visual Studio Code workspace history |
|||
.vscode/* |
|||
!.vscode/settings.json |
|||
!.vscode/tasks.json |
|||
!.vscode/launch.json |
|||
!.vscode/extensions.json |
|||
*.code-workspace |
|||
|
|||
# Rider |
|||
.idea/ |
|||
*.sln.iml |
|||
|
|||
# Migrations, auto-generated files |
|||
_ReSharper*/ |
|||
*.[Rr]e[Ss]harper |
|||
*.DotSettings.user |
|||
|
|||
# DotCover |
|||
*.dotCover |
|||
|
|||
# Visual Studio profiler |
|||
*.psess |
|||
*.vsp |
|||
*.vspx |
|||
*.sap |
|||
|
|||
# TFS 2012 Local Workspace |
|||
$tf/ |
|||
|
|||
# Guidance Automation Toolkit |
|||
*.gpState |
|||
|
|||
# ReSharper |
|||
_ReSharper*/ |
|||
*.[Rr]e[Ss]harper |
|||
*.DotSettings.user |
|||
|
|||
# JustCode |
|||
.JustCode |
|||
|
|||
# TeamCity |
|||
_TeamCity* |
|||
|
|||
# DotTrace |
|||
*.dotTrace |
|||
|
|||
# NCrunch |
|||
_NCrunch_* |
|||
.*crunch*.local.xml |
|||
nCrunchTemp_* |
|||
|
|||
# MightyMoose |
|||
*.mm.* |
|||
AutoTest.Net/ |
|||
|
|||
# Web workbench (sass) |
|||
.sass-cache/ |
|||
|
|||
# Installshield output folder |
|||
[Ee]xpress/ |
|||
|
|||
# DocProject |
|||
DocProject/buildhelp/ |
|||
DocProject/Help/*.HxT |
|||
DocProject/Help/*.HxC |
|||
DocProject/Help/*.hhc |
|||
DocProject/Help/*.hhk |
|||
DocProject/Help/*.hhp |
|||
DocProject/Help/Html2 |
|||
DocProject/Help/html |
|||
|
|||
# Click-Once directory |
|||
publish/ |
|||
|
|||
# Publish Web Output |
|||
*.[Pp]ublish.xml |
|||
*.azurePubxml |
|||
*.pubxml |
|||
*.publishproj |
|||
|
|||
# Azure Web App publish settings. Comment the next line if you want to |
|||
# checkin your Azure Web App publish settings, but sensitive information |
|||
# contained in these files will be unencrypted |
|||
PublishProfiles/ |
|||
|
|||
# NuGet Packages |
|||
*.nupkg |
|||
# The packages folder can be ignored because of Package Restore |
|||
**/[Pp]ackages/* |
|||
# except build/, which is used as an MSBuild target. |
|||
!**/[Pp]ackages/build/ |
|||
# Uncomment if necessary however generally it will be regenerated when needed |
|||
#!**/[Pp]ackages/repositories.config |
|||
# NuGet v3's project.json files produces more ignorable files |
|||
*.nuget.props |
|||
*.nuget.targets |
|||
|
|||
# Microsoft Azure Build Output |
|||
csx/ |
|||
*.build.csdef |
|||
|
|||
# Microsoft Azure Emulator |
|||
ecf/ |
|||
rcf/ |
|||
|
|||
# Windows Store app package directories and files |
|||
AppPackages/ |
|||
BundleArtifacts/ |
|||
Package.StoreAssociation.xml |
|||
_pkginfo.txt |
|||
*.appx |
|||
*.appxbundle |
|||
*.appxupload |
|||
|
|||
# Visual Studio cache files |
|||
# files ending in .cache can be ignored |
|||
*.[Cc]ache |
|||
# but keep track of directories ending in .cache |
|||
!*.[Cc]ache/ |
|||
|
|||
# Others |
|||
ClientBin/ |
|||
~$* |
|||
*~ |
|||
*.dbmdl |
|||
*.bak |
|||
*.orig |
|||
*.tmp |
|||
*.log |
|||
*.svclog |
|||
*.scc |
|||
|
|||
# Avalonia build outputs |
|||
publish-linux/ |
|||
publish-linux.bat |
|||
publish-linux.ps1 |
|||
|
|||
# Visual Studio generated files |
|||
*.pdb |
|||
*.opendb |
|||
*.VC.db |
|||
*.VC.VC.opendb |
|||
|
|||
# Entity Framework |
|||
Migrations/ |
|||
|
|||
# Razor cache |
|||
*.rz~ |
|||
|
|||
# Backup & report files from converting an old project file |
|||
*.Backup |
|||
*.old |
|||
*.Report.xml |
|||
|
|||
# SQL Server files |
|||
*.mdf |
|||
*.ldf |
|||
*.ndf |
|||
|
|||
# Business Intelligence projects |
|||
*.rdl.data |
|||
*.bim.layout |
|||
*.bim_*.settings |
|||
*.rptproj.rsuser |
|||
*- [Bb]ackup.rdl |
|||
*.rptproj.user |
|||
|
|||
# Microsoft Fakes |
|||
FakesAssemblies/ |
|||
|
|||
# GhostDoc plugin setting file |
|||
*.GhostDoc.xml |
|||
|
|||
# Node.js Tools for Visual Studio |
|||
.ntvs_analysis.dat |
|||
node_modules/ |
|||
|
|||
# Visual Studio 6 build log |
|||
*.plg |
|||
|
|||
# Visual Studio 6 workspace options file |
|||
*.opt |
|||
|
|||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) |
|||
*.vbw |
|||
|
|||
# Visual Studio LightSwitch build output |
|||
GeneratedArtifacts/ |
|||
_Pvt_Extensions/ |
|||
ModelManifest.xml |
|||
|
|||
# Paket dependency manager |
|||
.paket/paket.exe |
|||
paket-files/ |
|||
|
|||
# FAKE - F# Make |
|||
.fake/ |
|||
|
|||
# CodeRush personal settings |
|||
.cr/personal |
|||
|
|||
# Python Tools for Visual Studio (PTVS) |
|||
__pycache__/ |
|||
*.pyc |
|||
|
|||
# Cake |
|||
tools/** |
|||
!tools/packages.config |
|||
|
|||
# Tabs Studio |
|||
*.tss |
|||
|
|||
# Telerik's JustMock configuration file |
|||
*.jmconfig |
|||
|
|||
# BizTalk build output |
|||
*.btp.cs |
|||
*.btm.cs |
|||
*.odx.cs |
|||
*.xsd.cs |
|||
|
|||
# OpenCover UI analysis results |
|||
OpenCover/ |
|||
|
|||
# Azure Stream Analytics local run output |
|||
ASALocalRun/ |
|||
|
|||
# MSBuild Binary and Structured Log |
|||
*.binlog |
|||
|
|||
# NVidia Nsight GPU debugger configuration file |
|||
*.nvuser |
|||
|
|||
# MFractors (Xamarin productivity tool) working folder |
|||
.mfractor/ |
|||
|
|||
# Local History for Visual Studio |
|||
.localhistory/ |
|||
|
|||
# BeatPulse healthcheck temp database |
|||
healthchecksdb |
|||
|
|||
# Backup folder for Package Reference Convert tool in Visual Studio 2017 |
|||
MigrationBackup/ |
|||
|
|||
# Ionide (cross platform F# VS Code tools) working folder |
|||
.ionide/ |
|||
|
|||
# Fody - auto-generated XML schema |
|||
FodyWeavers.xsd |
|||
|
|||
# Avalonia persisting inspector and XAML designer cache |
|||
.Avalonia |
|||
|
|||
# Rider package caches |
|||
.idea/.idea.contentModel.xml |
|||
|
|||
# Temporary files |
|||
*.tmp |
|||
*.temp |
|||
|
|||
# Compiled binary caches |
|||
*.dll |
|||
*.exe |
|||
*.so |
|||
*.dylib |
|||
*.a |
|||
*.lib |
|||
@ -0,0 +1,65 @@ |
|||
using Avalonia; |
|||
using Avalonia.Data; |
|||
using AvaloniaEdit; |
|||
using AvaloniaEdit.Document; |
|||
|
|||
namespace MyAvaloniaApp.Attached; |
|||
|
|||
/// <summary>
|
|||
/// 为 <see cref="TextEditor"/> 提供可绑定的 <see cref="TextDocument"/> 附加属性,
|
|||
/// 便于在 MVVM 模式下直接绑定到 ViewModel。
|
|||
/// </summary>
|
|||
public static class TextEditorAssist |
|||
{ |
|||
public static readonly AttachedProperty<TextDocument?> DocumentProperty = |
|||
AvaloniaProperty.RegisterAttached<TextEditor, TextDocument?>( |
|||
"Document", |
|||
typeof(TextEditorAssist), |
|||
defaultBindingMode: BindingMode.TwoWay); |
|||
|
|||
private static readonly AttachedProperty<bool> IsInternalUpdateProperty = |
|||
AvaloniaProperty.RegisterAttached<TextEditor, bool>( |
|||
"IsInternalUpdate", |
|||
typeof(TextEditorAssist)); |
|||
|
|||
static TextEditorAssist() |
|||
{ |
|||
DocumentProperty.Changed.AddClassHandler<TextEditor>(OnDocumentPropertyChanged); |
|||
TextEditor.DocumentProperty.Changed.AddClassHandler<TextEditor>(OnEditorDocumentChanged); |
|||
} |
|||
|
|||
public static void SetDocument(TextEditor editor, TextDocument? value) => |
|||
editor.SetValue(DocumentProperty, value); |
|||
|
|||
public static TextDocument? GetDocument(TextEditor editor) => |
|||
editor.GetValue(DocumentProperty); |
|||
|
|||
private static void OnDocumentPropertyChanged(TextEditor editor, AvaloniaPropertyChangedEventArgs change) |
|||
{ |
|||
if (editor.GetValue(IsInternalUpdateProperty)) |
|||
return; |
|||
|
|||
var document = change.NewValue as TextDocument; |
|||
if (!ReferenceEquals(editor.Document, document)) |
|||
{ |
|||
editor.SetValue(IsInternalUpdateProperty, true); |
|||
editor.Document = document; |
|||
editor.SetValue(IsInternalUpdateProperty, false); |
|||
} |
|||
} |
|||
|
|||
private static void OnEditorDocumentChanged(TextEditor editor, AvaloniaPropertyChangedEventArgs change) |
|||
{ |
|||
if (editor.GetValue(IsInternalUpdateProperty)) |
|||
return; |
|||
|
|||
var document = change.NewValue as TextDocument; |
|||
if (!ReferenceEquals(editor.GetValue(DocumentProperty), document)) |
|||
{ |
|||
editor.SetValue(IsInternalUpdateProperty, true); |
|||
editor.SetValue(DocumentProperty, document); |
|||
editor.SetValue(IsInternalUpdateProperty, false); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,124 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Avalonia; |
|||
using AvaloniaEdit; |
|||
using AvaloniaEdit.TextMate; |
|||
using TextMateSharp.Grammars; |
|||
|
|||
namespace MyAvaloniaApp.Attached; |
|||
|
|||
/// <summary>
|
|||
/// 为 <see cref="TextEditor"/> 提供基于 TextMate 的语法高亮附加属性,
|
|||
/// 通过 MVVM 绑定即可切换语法与主题。
|
|||
/// </summary>
|
|||
public static class TextMateHelper |
|||
{ |
|||
public static readonly AttachedProperty<string?> LanguageProperty = |
|||
AvaloniaProperty.RegisterAttached<TextEditor, string?>( |
|||
"Language", |
|||
typeof(TextMateHelper)); |
|||
|
|||
private static readonly AttachedProperty<RegistryOptions?> RegistryOptionsProperty = |
|||
AvaloniaProperty.RegisterAttached<TextEditor, RegistryOptions?>( |
|||
"RegistryOptions", |
|||
typeof(TextMateHelper)); |
|||
|
|||
private static readonly AttachedProperty<TextMate.Installation?> InstallationProperty = |
|||
AvaloniaProperty.RegisterAttached<TextEditor, TextMate.Installation?>( |
|||
"Installation", |
|||
typeof(TextMateHelper)); |
|||
|
|||
private static readonly IReadOnlyDictionary<string, string> LanguageScopes = |
|||
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) |
|||
{ |
|||
["C#"] = "source.cs", |
|||
["JavaScript"] = "source.js", |
|||
["TypeScript"] = "source.ts", |
|||
["HTML"] = "text.html.basic", |
|||
["CSS"] = "source.css", |
|||
["JSON"] = "source.json", |
|||
["XML"] = "text.xml", |
|||
["Python"] = "source.python", |
|||
["Java"] = "source.java", |
|||
["SQL"] = "source.sql" |
|||
}; |
|||
|
|||
static TextMateHelper() => LanguageProperty.Changed.AddClassHandler<TextEditor>(OnLanguageChanged); |
|||
|
|||
public static void SetLanguage(TextEditor editor, string? value) => |
|||
editor.SetValue(LanguageProperty, value); |
|||
|
|||
public static string? GetLanguage(TextEditor editor) => |
|||
editor.GetValue(LanguageProperty); |
|||
|
|||
private static void OnLanguageChanged(TextEditor editor, AvaloniaPropertyChangedEventArgs change) |
|||
{ |
|||
var language = change.NewValue as string; |
|||
var registryOptions = EnsureRegistryOptions(editor); |
|||
var installation = EnsureInstallation(editor, registryOptions); |
|||
|
|||
if (installation == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var scope = ResolveScope(language); |
|||
|
|||
if (!string.IsNullOrWhiteSpace(scope)) |
|||
{ |
|||
try |
|||
{ |
|||
installation.SetGrammar(scope); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine($"TextMateHelper: 设置语法失败 - {ex.Message}"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private static RegistryOptions EnsureRegistryOptions(TextEditor editor) |
|||
{ |
|||
var registryOptions = editor.GetValue(RegistryOptionsProperty); |
|||
|
|||
if (registryOptions == null) |
|||
{ |
|||
registryOptions = new RegistryOptions(ThemeName.DarkPlus); |
|||
editor.SetValue(RegistryOptionsProperty, registryOptions); |
|||
} |
|||
|
|||
return registryOptions; |
|||
} |
|||
|
|||
private static TextMate.Installation? EnsureInstallation(TextEditor editor, RegistryOptions registryOptions) |
|||
{ |
|||
var installation = editor.GetValue(InstallationProperty); |
|||
if (installation == null) |
|||
{ |
|||
try |
|||
{ |
|||
installation = editor.InstallTextMate(registryOptions); |
|||
editor.SetValue(InstallationProperty, installation); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
System.Diagnostics.Debug.WriteLine($"TextMateHelper: 安装失败 - {ex.Message}"); |
|||
} |
|||
} |
|||
|
|||
return installation; |
|||
} |
|||
|
|||
private static string ResolveScope(string? language) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(language)) |
|||
{ |
|||
return "source.cs"; |
|||
} |
|||
|
|||
return LanguageScopes.TryGetValue(language, out var value) |
|||
? value |
|||
: "source.cs"; |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,352 @@ |
|||
using Avalonia.Media; |
|||
using Avalonia.Threading; |
|||
using HeroIconsAvalonia.Enums; |
|||
using ReactiveUI; |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Reactive; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace MyAvaloniaApp.ViewModels.Pages; |
|||
|
|||
/// <summary>
|
|||
/// DialogHost 示例页面的 ViewModel
|
|||
/// </summary>
|
|||
public class DialogHostPageViewModel : ReactiveObject |
|||
{ |
|||
private bool _isDialogOpen; |
|||
private string _dialogTitle = "提示"; |
|||
private string _dialogMessage = "请选择需要执行的操作"; |
|||
private string _lastActionMessage = string.Empty; |
|||
private bool _rememberChoice; |
|||
private bool _isRememberChoiceVisible = true; |
|||
private IconType _dialogIcon = IconType.InformationCircle; |
|||
private IBrush _dialogAccentBrush = new SolidColorBrush(Color.FromRgb(59, 130, 246)); |
|||
private string _primaryButtonText = "确认"; |
|||
private string _secondaryButtonText = "取消"; |
|||
private bool _isPrimaryButtonVisible = true; |
|||
private bool _useAutoClose; |
|||
private TimeSpan _autoCloseDelay = TimeSpan.FromSeconds(2); |
|||
private CancellationTokenSource? _autoCloseCts; |
|||
|
|||
public DialogHostPageViewModel() |
|||
{ |
|||
ShowDialogCommand = ReactiveCommand.Create<string?>(ShowDialog); |
|||
ConfirmDialogCommand = ReactiveCommand.Create(ConfirmDialog); |
|||
CancelDialogCommand = ReactiveCommand.Create(CancelDialog); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否展示对话框
|
|||
/// </summary>
|
|||
public bool IsDialogOpen |
|||
{ |
|||
get => _isDialogOpen; |
|||
set => this.RaiseAndSetIfChanged(ref _isDialogOpen, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 对话框标题
|
|||
/// </summary>
|
|||
public string DialogTitle |
|||
{ |
|||
get => _dialogTitle; |
|||
set => this.RaiseAndSetIfChanged(ref _dialogTitle, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 对话框消息
|
|||
/// </summary>
|
|||
public string DialogMessage |
|||
{ |
|||
get => _dialogMessage; |
|||
set => this.RaiseAndSetIfChanged(ref _dialogMessage, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 记住选择
|
|||
/// </summary>
|
|||
public bool RememberChoice |
|||
{ |
|||
get => _rememberChoice; |
|||
set => this.RaiseAndSetIfChanged(ref _rememberChoice, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 最近一次操作反馈
|
|||
/// </summary>
|
|||
public string LastActionMessage |
|||
{ |
|||
get => _lastActionMessage; |
|||
set => this.RaiseAndSetIfChanged(ref _lastActionMessage, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 对话框图标
|
|||
/// </summary>
|
|||
public IconType DialogIcon |
|||
{ |
|||
get => _dialogIcon; |
|||
set => this.RaiseAndSetIfChanged(ref _dialogIcon, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 对话框强调色
|
|||
/// </summary>
|
|||
public IBrush DialogAccentBrush |
|||
{ |
|||
get => _dialogAccentBrush; |
|||
set => this.RaiseAndSetIfChanged(ref _dialogAccentBrush, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 主操作按钮文本
|
|||
/// </summary>
|
|||
public string PrimaryButtonText |
|||
{ |
|||
get => _primaryButtonText; |
|||
set => this.RaiseAndSetIfChanged(ref _primaryButtonText, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 次操作按钮文本
|
|||
/// </summary>
|
|||
public string SecondaryButtonText |
|||
{ |
|||
get => _secondaryButtonText; |
|||
set |
|||
{ |
|||
this.RaiseAndSetIfChanged(ref _secondaryButtonText, value); |
|||
this.RaisePropertyChanged(nameof(HasSecondaryButton)); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否展示次操作按钮
|
|||
/// </summary>
|
|||
public bool HasSecondaryButton => !string.IsNullOrWhiteSpace(_secondaryButtonText); |
|||
|
|||
/// <summary>
|
|||
/// 主操作按钮是否可见
|
|||
/// </summary>
|
|||
public bool IsPrimaryButtonVisible |
|||
{ |
|||
get => _isPrimaryButtonVisible; |
|||
set => this.RaiseAndSetIfChanged(ref _isPrimaryButtonVisible, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否展示“记住选择”选项
|
|||
/// </summary>
|
|||
public bool IsRememberChoiceVisible |
|||
{ |
|||
get => _isRememberChoiceVisible; |
|||
set => this.RaiseAndSetIfChanged(ref _isRememberChoiceVisible, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 是否启用自动关闭
|
|||
/// </summary>
|
|||
public bool UseAutoClose |
|||
{ |
|||
get => _useAutoClose; |
|||
private set => this.RaiseAndSetIfChanged(ref _useAutoClose, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 自动关闭延时时间
|
|||
/// </summary>
|
|||
public TimeSpan AutoCloseDelay |
|||
{ |
|||
get => _autoCloseDelay; |
|||
private set => this.RaiseAndSetIfChanged(ref _autoCloseDelay, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 展示对话框命令
|
|||
/// </summary>
|
|||
public ReactiveCommand<string?, Unit> ShowDialogCommand { get; } |
|||
|
|||
/// <summary>
|
|||
/// 确认操作命令
|
|||
/// </summary>
|
|||
public ReactiveCommand<Unit, Unit> ConfirmDialogCommand { get; } |
|||
|
|||
/// <summary>
|
|||
/// 取消操作命令
|
|||
/// </summary>
|
|||
public ReactiveCommand<Unit, Unit> CancelDialogCommand { get; } |
|||
|
|||
private void ShowDialog(string? parameter) |
|||
{ |
|||
CancelAutoCloseTimer(); |
|||
|
|||
var (variant, delayOverride) = ParseParameter(parameter); |
|||
ConfigureVariant(variant, delayOverride); |
|||
RememberChoice = false; |
|||
IsDialogOpen = true; |
|||
LastActionMessage = string.Empty; |
|||
|
|||
if (UseAutoClose) |
|||
{ |
|||
StartAutoCloseTimer(); |
|||
} |
|||
} |
|||
|
|||
private void ConfirmDialog() |
|||
{ |
|||
CancelAutoCloseTimer(); |
|||
IsDialogOpen = false; |
|||
var rememberSuffix = IsRememberChoiceVisible && RememberChoice ? "(记住选择)" : string.Empty; |
|||
LastActionMessage = $"已确认:{DialogTitle}{rememberSuffix}"; |
|||
} |
|||
|
|||
private void CancelDialog() |
|||
{ |
|||
CancelAutoCloseTimer(); |
|||
|
|||
if (!HasSecondaryButton) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
IsDialogOpen = false; |
|||
var rememberSuffix = IsRememberChoiceVisible && RememberChoice ? "(记住选择)" : string.Empty; |
|||
LastActionMessage = $"已取消:{DialogTitle}{rememberSuffix}"; |
|||
} |
|||
|
|||
private void ConfigureVariant(string? variant, TimeSpan? delayOverride) |
|||
{ |
|||
var key = string.IsNullOrWhiteSpace(variant) ? "info" : variant.Trim().ToLowerInvariant(); |
|||
|
|||
UseAutoClose = false; |
|||
AutoCloseDelay = delayOverride ?? TimeSpan.FromSeconds(2); |
|||
IsPrimaryButtonVisible = true; |
|||
SecondaryButtonText = "取消"; |
|||
PrimaryButtonText = "确认"; |
|||
IsRememberChoiceVisible = true; |
|||
|
|||
switch (key) |
|||
{ |
|||
case "success": |
|||
DialogTitle = "操作成功"; |
|||
DialogMessage = "所有任务都已顺利完成。您可以继续后续流程。"; |
|||
DialogIcon = IconType.CheckCircle; |
|||
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(34, 197, 94)); |
|||
PrimaryButtonText = string.Empty; |
|||
SecondaryButtonText = string.Empty; |
|||
IsRememberChoiceVisible = false; |
|||
IsPrimaryButtonVisible = false; |
|||
UseAutoClose = true; |
|||
break; |
|||
|
|||
case "error": |
|||
case "failure": |
|||
DialogTitle = "操作失败"; |
|||
DialogMessage = "执行过程中出现错误,请检查配置或稍后重试。"; |
|||
DialogIcon = IconType.XCircle; |
|||
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(239, 68, 68)); |
|||
PrimaryButtonText = string.Empty; |
|||
SecondaryButtonText = string.Empty; |
|||
IsRememberChoiceVisible = false; |
|||
IsPrimaryButtonVisible = false; |
|||
UseAutoClose = true; |
|||
break; |
|||
|
|||
case "warning": |
|||
DialogTitle = "风险提示"; |
|||
DialogMessage = "当前设置可能带来潜在风险,请在继续之前确认信息。"; |
|||
DialogIcon = IconType.ExclamationTriangle; |
|||
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(234, 179, 8)); |
|||
PrimaryButtonText = string.Empty; |
|||
SecondaryButtonText = string.Empty; |
|||
IsRememberChoiceVisible = false; |
|||
IsPrimaryButtonVisible = false; |
|||
UseAutoClose = true; |
|||
break; |
|||
|
|||
case "confirm": |
|||
DialogTitle = "确认操作"; |
|||
DialogMessage = "此操作会影响当前设置,请确认是否继续。"; |
|||
DialogIcon = IconType.QuestionMarkCircle; |
|||
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(59, 130, 246)); |
|||
PrimaryButtonText = "确认"; |
|||
SecondaryButtonText = "取消"; |
|||
IsRememberChoiceVisible = false; |
|||
break; |
|||
|
|||
case "info": |
|||
case "general": |
|||
default: |
|||
DialogTitle = "通用提示"; |
|||
DialogMessage = "执行此操作将应用更改,是否继续?您也可以勾选记住选择。"; |
|||
DialogIcon = IconType.InformationCircle; |
|||
DialogAccentBrush = new SolidColorBrush(Color.FromRgb(59, 130, 246)); |
|||
PrimaryButtonText = "确认"; |
|||
SecondaryButtonText = "取消"; |
|||
IsRememberChoiceVisible = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
private (string variant, TimeSpan? delayOverride) ParseParameter(string? parameter) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(parameter)) |
|||
{ |
|||
return ("info", null); |
|||
} |
|||
|
|||
var parts = parameter.Split(new[] { ':', '|', ';', ',' }, StringSplitOptions.RemoveEmptyEntries); |
|||
var variant = parts.Length > 0 ? parts[0].Trim() : "info"; |
|||
|
|||
if (parts.Length > 1 && double.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var seconds) && seconds > 0) |
|||
{ |
|||
return (variant, TimeSpan.FromSeconds(seconds)); |
|||
} |
|||
|
|||
return (variant, null); |
|||
} |
|||
|
|||
private void StartAutoCloseTimer() |
|||
{ |
|||
CancelAutoCloseTimer(); |
|||
|
|||
var delay = AutoCloseDelay; |
|||
var titleSnapshot = DialogTitle; |
|||
|
|||
_autoCloseCts = new CancellationTokenSource(); |
|||
var token = _autoCloseCts.Token; |
|||
|
|||
Task.Run(async () => |
|||
{ |
|||
try |
|||
{ |
|||
await Task.Delay(delay, token); |
|||
if (!token.IsCancellationRequested) |
|||
{ |
|||
await Dispatcher.UIThread.InvokeAsync(() => |
|||
{ |
|||
IsDialogOpen = false; |
|||
LastActionMessage = $"已自动关闭:{titleSnapshot}"; |
|||
}); |
|||
} |
|||
} |
|||
catch (TaskCanceledException) |
|||
{ |
|||
// 忽略取消
|
|||
} |
|||
}, token); |
|||
} |
|||
|
|||
private void CancelAutoCloseTimer() |
|||
{ |
|||
if (_autoCloseCts != null) |
|||
{ |
|||
_autoCloseCts.Cancel(); |
|||
_autoCloseCts.Dispose(); |
|||
_autoCloseCts = null; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,144 @@ |
|||
using Microsoft.Extensions.Logging; |
|||
using ReactiveUI; |
|||
using System; |
|||
using System.Collections.ObjectModel; |
|||
using System.Reactive; |
|||
using AvaloniaEdit.Document; |
|||
|
|||
namespace MyAvaloniaApp.ViewModels.Pages; |
|||
|
|||
/// <summary>
|
|||
/// 代码编辑器页面的 ViewModel
|
|||
/// </summary>
|
|||
public class EditorPageViewModel : ReactiveObject |
|||
{ |
|||
private string _selectedLanguage = "C#"; |
|||
private TextDocument _document; |
|||
|
|||
private readonly ILogger<EditorPageViewModel>? _logger; |
|||
|
|||
public ObservableCollection<string> AvailableLanguages { get; } |
|||
|
|||
public string SelectedLanguage |
|||
{ |
|||
get => _selectedLanguage; |
|||
set => this.RaiseAndSetIfChanged(ref _selectedLanguage, value); |
|||
} |
|||
|
|||
public TextDocument Document |
|||
{ |
|||
get => _document; |
|||
set => this.RaiseAndSetIfChanged(ref _document, value); |
|||
} |
|||
|
|||
// 响应式命令
|
|||
public ReactiveCommand<Unit, Unit> ClearCodeCommand { get; } |
|||
public ReactiveCommand<Unit, Unit> FormatCodeCommand { get; } |
|||
|
|||
public EditorPageViewModel(ILogger<EditorPageViewModel>? logger = null) |
|||
{ |
|||
_logger = logger; |
|||
|
|||
// 先初始化 Document,确保绑定时有值
|
|||
_document = new TextDocument(); |
|||
|
|||
AvailableLanguages = new ObservableCollection<string> |
|||
{ |
|||
"C#", |
|||
"JavaScript", |
|||
"TypeScript", |
|||
"HTML", |
|||
"CSS", |
|||
"JSON", |
|||
"XML", |
|||
"Python", |
|||
"Java", |
|||
"SQL" |
|||
}; |
|||
|
|||
_logger?.LogInformation("EditorPageViewModel 已创建"); |
|||
|
|||
// 初始化示例代码
|
|||
InitializeDefaultCode(); |
|||
|
|||
// 创建命令
|
|||
ClearCodeCommand = ReactiveCommand.Create(ClearCode); |
|||
FormatCodeCommand = ReactiveCommand.Create(FormatCode); |
|||
|
|||
// 监听语言选择变化
|
|||
this.WhenAnyValue(x => x.SelectedLanguage) |
|||
.Subscribe(lang => |
|||
{ |
|||
_logger?.LogInformation("切换语言: {Language}", lang); |
|||
UpdateCodeForLanguage(lang); |
|||
}); |
|||
} |
|||
|
|||
private void InitializeDefaultCode() |
|||
{ |
|||
var defaultCode = "// 欢迎使用 AvaloniaEdit.TextMate 代码编辑器\n" + |
|||
"// 选择不同的编程语言查看语法高亮效果\n" + |
|||
"\n" + |
|||
"using System;\n" + |
|||
"\n" + |
|||
"namespace MyAvaloniaApp\n" + |
|||
"{\n" + |
|||
" public class Program\n" + |
|||
" {\n" + |
|||
" public static void Main(string[] args)\n" + |
|||
" {\n" + |
|||
" Console.WriteLine(\"Hello, AvaloniaEdit!\");\n" + |
|||
" }\n" + |
|||
" }\n" + |
|||
"}"; |
|||
|
|||
Document.Text = defaultCode; |
|||
} |
|||
|
|||
private void UpdateCodeForLanguage(string language) |
|||
{ |
|||
Document.Text = GetDefaultCode(language); |
|||
_logger?.LogInformation("代码已更新为: {Language}", language); |
|||
} |
|||
|
|||
private string GetDefaultCode(string language) |
|||
{ |
|||
return language switch |
|||
{ |
|||
"C#" => "using System;\n\nnamespace Example\n{\n public class Demo\n {\n static void Main()\n {\n Console.WriteLine(\"Hello World!\");\n }\n }\n}", |
|||
|
|||
"JavaScript" => "// JavaScript 示例\nfunction greet(name) {\n return `Hello, ${name}!`;\n}\n\nconst person = 'World';\nconsole.log(greet(person));", |
|||
|
|||
"TypeScript" => "// TypeScript 示例\ninterface Person {\n name: string;\n age: number;\n}\n\nconst user: Person = {\n name: 'Alice',\n age: 30\n};\n\nconsole.log(user);", |
|||
|
|||
"HTML" => "<!DOCTYPE html>\n<html>\n<head>\n <title>示例</title>\n</head>\n<body>\n <h1>Hello World</h1>\n</body>\n</html>", |
|||
|
|||
"CSS" => "/* CSS 示例 */\nbody {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 20px;\n}\n\n.container {\n max-width: 1200px;\n margin: 0 auto;\n}", |
|||
|
|||
"JSON" => "{\n \"name\": \"MyApp\",\n \"version\": \"1.0.0\",\n \"dependencies\": {}\n}", |
|||
|
|||
"XML" => "<?xml version=\"1.0\"?>\n<root>\n <item>示例数据</item>\n</root>", |
|||
|
|||
"Python" => "# Python 示例\ndef greet(name):\n return f'Hello, {name}!'\n\nprint(greet('World'))", |
|||
|
|||
"Java" => "public class Example {\n public static void main(String[] args) {\n System.out.println(\"Hello World\");\n }\n}", |
|||
|
|||
"SQL" => "-- SQL 示例\nSELECT * FROM Users;\n\nINSERT INTO Users (name, email) VALUES ('John', 'john@example.com');", |
|||
|
|||
_ => "// 未支持的编程语言" |
|||
}; |
|||
} |
|||
|
|||
private void ClearCode() |
|||
{ |
|||
Document.Text = string.Empty; |
|||
_logger?.LogInformation("代码已清空"); |
|||
} |
|||
|
|||
private void FormatCode() |
|||
{ |
|||
_logger?.LogInformation("格式化代码: {Language}", SelectedLanguage); |
|||
// 这里可以添加代码格式化逻辑
|
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,163 @@ |
|||
<UserControl 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:MyAvaloniaApp.ViewModels.Pages" |
|||
xmlns:dialogHost="clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia" |
|||
xmlns:heroicons="clr-namespace:HeroIconsAvalonia.Controls;assembly=HeroIconsAvalonia" |
|||
mc:Ignorable="d" |
|||
x:Class="MyAvaloniaApp.Views.Pages.DialogHostPageView" |
|||
x:DataType="vm:DialogHostPageViewModel"> |
|||
|
|||
<Design.DataContext> |
|||
<vm:DialogHostPageViewModel /> |
|||
</Design.DataContext> |
|||
|
|||
<dialogHost:DialogHost IsOpen="{Binding IsDialogOpen}"> |
|||
<dialogHost:DialogHost.DialogContent> |
|||
<Border Background="{StaticResource BackgroundWhite}" |
|||
CornerRadius="16" |
|||
Padding="24" |
|||
Width="380"> |
|||
<StackPanel Spacing="18"> |
|||
<Grid ColumnDefinitions="Auto,*" ColumnSpacing="12"> |
|||
<Border Grid.Column="0" |
|||
Width="40" |
|||
Height="40" |
|||
CornerRadius="20" |
|||
Background="{Binding DialogAccentBrush}" |
|||
VerticalAlignment="Center"> |
|||
<heroicons:HeroIcon Type="{Binding DialogIcon}" |
|||
Width="22" |
|||
Height="22" |
|||
Foreground="White" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center"/> |
|||
</Border> |
|||
<StackPanel Grid.Column="1" Spacing="6"> |
|||
<TextBlock Text="{Binding DialogTitle}" |
|||
FontSize="18" |
|||
FontWeight="SemiBold" |
|||
Foreground="{StaticResource TextPrimary}"/> |
|||
<TextBlock Text="{Binding DialogMessage}" |
|||
TextWrapping="Wrap" |
|||
FontSize="14" |
|||
Foreground="{StaticResource SecondaryGrayDark}" |
|||
MaxWidth="260"/> |
|||
</StackPanel> |
|||
</Grid> |
|||
|
|||
<CheckBox Content="记住我的选择" |
|||
IsChecked="{Binding RememberChoice}" |
|||
Margin="0,4,0,0" |
|||
IsVisible="{Binding IsRememberChoiceVisible}"/> |
|||
|
|||
<StackPanel Orientation="Horizontal" |
|||
HorizontalAlignment="Right" |
|||
Spacing="10"> |
|||
<Button Content="{Binding SecondaryButtonText}" |
|||
MinWidth="96" |
|||
Command="{Binding CancelDialogCommand}" |
|||
IsVisible="{Binding HasSecondaryButton}"/> |
|||
<Button Content="{Binding PrimaryButtonText}" |
|||
MinWidth="96" |
|||
Command="{Binding ConfirmDialogCommand}" |
|||
Background="{Binding DialogAccentBrush}" |
|||
Foreground="White" |
|||
BorderThickness="0" |
|||
CornerRadius="8" |
|||
IsVisible="{Binding IsPrimaryButtonVisible}"/> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</Border> |
|||
</dialogHost:DialogHost.DialogContent> |
|||
|
|||
<Grid RowDefinitions="Auto,Auto,*" ColumnDefinitions="*" Margin="20" Background="Transparent"> |
|||
<StackPanel Spacing="8"> |
|||
<TextBlock Text="DialogHost 示例" |
|||
FontSize="20" |
|||
FontWeight="SemiBold" |
|||
Foreground="{StaticResource TextPrimary}"/> |
|||
<TextBlock Text="点击下方按钮体验 DialogHost.Avalonia 提供的模态对话框。" |
|||
FontSize="14" |
|||
Foreground="{StaticResource SecondaryGrayDark}"/> |
|||
</StackPanel> |
|||
|
|||
<WrapPanel Grid.Row="1" |
|||
Margin="0,18,0,0" |
|||
Orientation="Horizontal"> |
|||
<Button Content="通用提示" |
|||
Padding="18,10" |
|||
Margin="0,0,12,12" |
|||
Command="{Binding ShowDialogCommand}" |
|||
CommandParameter="info" |
|||
Background="#1E3B82F6" |
|||
BorderBrush="Transparent" |
|||
Foreground="{StaticResource TextPrimary}" |
|||
CornerRadius="10"/> |
|||
<Button Content="确认弹窗" |
|||
Padding="18,10" |
|||
Margin="0,0,12,12" |
|||
Command="{Binding ShowDialogCommand}" |
|||
CommandParameter="confirm" |
|||
Background="#1E2563FF" |
|||
BorderBrush="Transparent" |
|||
Foreground="White" |
|||
CornerRadius="10"/> |
|||
<Button Content="成功提示" |
|||
Padding="18,10" |
|||
Margin="0,0,12,12" |
|||
Command="{Binding ShowDialogCommand}" |
|||
CommandParameter="success" |
|||
Background="#FF22C55E" |
|||
BorderBrush="Transparent" |
|||
Foreground="White" |
|||
CornerRadius="10"/> |
|||
<Button Content="失败提示" |
|||
Padding="18,10" |
|||
Margin="0,0,12,12" |
|||
Command="{Binding ShowDialogCommand}" |
|||
CommandParameter="error" |
|||
Background="#FFEF4444" |
|||
BorderBrush="Transparent" |
|||
Foreground="White" |
|||
CornerRadius="10"/> |
|||
<Button Content="警告提示" |
|||
Padding="18,10" |
|||
Margin="0,0,12,12" |
|||
Command="{Binding ShowDialogCommand}" |
|||
CommandParameter="warning" |
|||
Background="#FFF59E0B" |
|||
BorderBrush="Transparent" |
|||
Foreground="{StaticResource TextPrimary}" |
|||
CornerRadius="10"/> |
|||
<Button Content="成功提示(5s)" |
|||
Padding="18,10" |
|||
Margin="0,0,12,12" |
|||
Command="{Binding ShowDialogCommand}" |
|||
CommandParameter="success:5" |
|||
Background="#1422C55E" |
|||
BorderBrush="Transparent" |
|||
Foreground="White" |
|||
CornerRadius="10"/> |
|||
</WrapPanel> |
|||
|
|||
<Border Grid.Row="2" |
|||
Margin="0,24,0,0" |
|||
Padding="16" |
|||
Background="{StaticResource BackgroundLight}" |
|||
BorderBrush="{StaticResource BorderLight}" |
|||
BorderThickness="1" |
|||
CornerRadius="8"> |
|||
<StackPanel Spacing="6"> |
|||
<TextBlock Text="最近操作" |
|||
FontSize="16" |
|||
FontWeight="SemiBold" |
|||
Foreground="{StaticResource TextPrimary}"/> |
|||
<TextBlock Text="{Binding LastActionMessage, FallbackValue=尚未进行任何操作}"/> |
|||
</StackPanel> |
|||
</Border> |
|||
</Grid> |
|||
</dialogHost:DialogHost> |
|||
</UserControl> |
|||
|
|||
@ -0,0 +1,12 @@ |
|||
using Avalonia.Controls; |
|||
|
|||
namespace MyAvaloniaApp.Views.Pages; |
|||
|
|||
public partial class DialogHostPageView : UserControl |
|||
{ |
|||
public DialogHostPageView() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,129 @@ |
|||
<UserControl 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:MyAvaloniaApp.ViewModels.Pages" |
|||
xmlns:converters="using:MyAvaloniaApp.Converters" |
|||
xmlns:avaloniaEdit="clr-namespace:AvaloniaEdit;assembly=AvaloniaEdit" |
|||
xmlns:attached="using:MyAvaloniaApp.Attached" |
|||
xmlns:heroicons="clr-namespace:HeroIconsAvalonia.Controls;assembly=HeroIconsAvalonia" |
|||
mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="800" |
|||
x:Class="MyAvaloniaApp.Views.Pages.EditorPageView" |
|||
x:DataType="vm:EditorPageViewModel"> |
|||
|
|||
<Design.DataContext> |
|||
<vm:EditorPageViewModel /> |
|||
</Design.DataContext> |
|||
|
|||
<Grid> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto"/> |
|||
<RowDefinition Height="*"/> |
|||
</Grid.RowDefinitions> |
|||
|
|||
<!-- 页面标题和工具栏 --> |
|||
<Border Grid.Row="0" |
|||
Background="{StaticResource BackgroundLight}" |
|||
BorderBrush="{StaticResource BorderLight}" |
|||
BorderThickness="0,0,0,1" |
|||
Padding="20"> |
|||
<StackPanel Spacing="15"> |
|||
<!-- 标题 --> |
|||
<TextBlock Text="代码编辑器 - AvaloniaEdit.TextMate" |
|||
FontSize="24" |
|||
FontWeight="Bold" |
|||
Foreground="{StaticResource TextPrimary}"/> |
|||
|
|||
<TextBlock Text="基于 AvaloniaEdit 的强大代码编辑器,支持语法高亮、智能提示等功能" |
|||
FontSize="14" |
|||
Foreground="{StaticResource SecondaryGrayDark}" |
|||
Margin="0,5,0,0"/> |
|||
|
|||
<!-- 工具栏 --> |
|||
<StackPanel Orientation="Horizontal" Spacing="15" Margin="0,10,0,0"> |
|||
<!-- 语言选择 --> |
|||
<StackPanel Orientation="Horizontal" Spacing="8"> |
|||
<TextBlock Text="编程语言:" |
|||
FontSize="14" |
|||
FontWeight="SemiBold" |
|||
Foreground="{StaticResource TextPrimary}" |
|||
VerticalAlignment="Center"/> |
|||
<ComboBox ItemsSource="{Binding AvailableLanguages}" |
|||
SelectedItem="{Binding SelectedLanguage}" |
|||
Width="150" |
|||
VerticalAlignment="Center"> |
|||
<ComboBox.ItemTemplate> |
|||
<DataTemplate> |
|||
<TextBlock Text="{Binding}"/> |
|||
</DataTemplate> |
|||
</ComboBox.ItemTemplate> |
|||
</ComboBox> |
|||
</StackPanel> |
|||
|
|||
<!-- 操作按钮 --> |
|||
<Button Content="清空代码" |
|||
Command="{Binding ClearCodeCommand}" |
|||
HorizontalAlignment="Left" |
|||
VerticalAlignment="Center"> |
|||
<Button.Template> |
|||
<ControlTemplate> |
|||
<Border Background="{StaticResource BackgroundWhite}" |
|||
BorderBrush="{StaticResource BorderMedium}" |
|||
BorderThickness="1" |
|||
CornerRadius="6" |
|||
Padding="12,8"> |
|||
<ContentPresenter Content="{TemplateBinding Content}"/> |
|||
</Border> |
|||
</ControlTemplate> |
|||
</Button.Template> |
|||
</Button> |
|||
|
|||
<Button Content="格式化" |
|||
Command="{Binding FormatCodeCommand}" |
|||
HorizontalAlignment="Left" |
|||
VerticalAlignment="Center"> |
|||
<Button.Template> |
|||
<ControlTemplate> |
|||
<Border Background="{StaticResource BackgroundWhite}" |
|||
BorderBrush="{StaticResource BorderMedium}" |
|||
BorderThickness="1" |
|||
CornerRadius="6" |
|||
Padding="12,8"> |
|||
<ContentPresenter Content="{TemplateBinding Content}"/> |
|||
</Border> |
|||
</ControlTemplate> |
|||
</Button.Template> |
|||
</Button> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</Border> |
|||
|
|||
<!-- 代码编辑器 --> |
|||
<Grid Grid.Row="1" Margin="5"> |
|||
<Border Background="{StaticResource BackgroundWhite}" |
|||
BorderBrush="{StaticResource BorderMedium}" |
|||
BorderThickness="1" |
|||
CornerRadius="8" |
|||
Padding="0"> |
|||
<avaloniaEdit:TextEditor x:Name="TextEditor" |
|||
attached:TextEditorAssist.Document="{Binding Document}" |
|||
attached:TextMateHelper.Language="{Binding SelectedLanguage}" |
|||
FontFamily="Consolas, 'Courier New', monospace" |
|||
FontSize="14" |
|||
ShowLineNumbers="True" |
|||
WordWrap="False" |
|||
Margin="10"> |
|||
<avaloniaEdit:TextEditor.Styles> |
|||
<Style Selector="avaloniaEdit|TextEditor"> |
|||
<Setter Property="Background" Value="{StaticResource BackgroundWhite}"/> |
|||
<Setter Property="Foreground" Value="{StaticResource TextPrimary}"/> |
|||
</Style> |
|||
<Style Selector="avaloniaEdit|TextEditor:focus"> |
|||
<Setter Property="Background" Value="{StaticResource BackgroundWhite}"/> |
|||
</Style> |
|||
</avaloniaEdit:TextEditor.Styles> |
|||
</avaloniaEdit:TextEditor> |
|||
</Border> |
|||
</Grid> |
|||
</Grid> |
|||
</UserControl> |
|||
@ -0,0 +1,20 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Markup.Xaml; |
|||
|
|||
namespace MyAvaloniaApp.Views.Pages; |
|||
|
|||
/// <summary>
|
|||
/// 代码编辑器页面的 View
|
|||
/// </summary>
|
|||
public partial class EditorPageView : UserControl |
|||
{ |
|||
public EditorPageView() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
private void InitializeComponent() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
} |
|||
} |
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +1 @@ |
|||
6e01c74e1c21b9706e5c2eb7e4b73fafcd6b61916a627af46c2ec5b3700097d5 |
|||
a9f27ce4bdac4bf5ca954160904d645cef7a4bde57bc6b530b0206ad45cc8eb7 |
|||
|
|||
Binary file not shown.
@ -1 +1 @@ |
|||
bf952ee0722a6225039d842c594a8ebe310a83a2db3935d66a759729adc67724 |
|||
766f73ce23faadf06c3dea8c85c8321692de9c1311687760c1eb88fe735925f7 |
|||
|
|||
Binary file not shown.
Binary file not shown.
@ -1 +1 @@ |
|||
2fb62cbdfb8208998e89466afbadbb20df4541f3eb58228e330c9ae62600a000 |
|||
7e0e71ecbe1dda5d9b13b4a0f67a04828398b765cd3833716ab133f8c26dd1a4 |
|||
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +1 @@ |
|||
9067b32390c3062370b40b528526728b26c9b8c7a8e74dc8af0e7cbbcae48cc3 |
|||
c4c294d354420aa37ac28b90b6579ec6e118659488679dbc5a071ae852a5bade |
|||
|
|||
Binary file not shown.
@ -1 +1 @@ |
|||
3ff08d4c1a2a8d89d5383dc9190935873755fc8f8e541fbc6f37c55291a0c028 |
|||
cb222c9b1a7e6b974825e9997ad1ff3ee2ea91da885ea5a9eff2111dc7b6c82a |
|||
|
|||
Binary file not shown.
Binary file not shown.
@ -1 +1 @@ |
|||
40d226aca90a8aa1a045c119f771f7c4b7a24c5170b7abdc97c79504e72819c2 |
|||
b62578fea8a18dfe5105a2e709cb315832fb6358bebf41ee063ccc3efd6c5c11 |
|||
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue