feat: support view model closing view window
This commit is contained in:
@@ -17,13 +17,11 @@
|
||||
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.4.0" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageReference Include="DotNetZip" Version="1.9.1.8" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.142" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="10.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Frontend\Models\" />
|
||||
<Folder Include="Frontend\Utils\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
using Microsoft.Xaml.Behaviors;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Behaviors {
|
||||
public class ConfirmCloseBehavior : Behavior<Window> {
|
||||
|
||||
public ICommand ConfirmCommand {
|
||||
get { return (ICommand)GetValue(ConfirmCommandProperty); }
|
||||
set { SetValue(ConfirmCommandProperty, value); }
|
||||
}
|
||||
|
||||
// Using a DependencyProperty as the backing store for ConfirmCommand. This enables animation, styling, binding, etc...
|
||||
public static readonly DependencyProperty ConfirmCommandProperty =
|
||||
DependencyProperty.Register("ConfirmCommand", typeof(ICommand), typeof(ConfirmCloseBehavior));
|
||||
|
||||
|
||||
protected override void OnAttached() {
|
||||
base.OnAttached();
|
||||
AssociatedObject.Closing += OnClosing;
|
||||
}
|
||||
|
||||
protected override void OnDetaching() {
|
||||
AssociatedObject.Closing -= OnClosing;
|
||||
base.OnDetaching();
|
||||
}
|
||||
|
||||
private void OnClosing(object? sender, CancelEventArgs e) {
|
||||
if (ConfirmCommand?.CanExecute(null) == true) {
|
||||
// 假设Command返回 bool 或通过回调/事件通知结果
|
||||
bool allowClose = (Func<object?, bool>)ConfirmCommand.Execute(null);
|
||||
e.Cancel = !allowClose;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Shared {
|
||||
public static class BrowserHelper {
|
||||
public static void OpenInDefaultBrowser(string url) {
|
||||
if (string.IsNullOrWhiteSpace(url)) {
|
||||
throw new ArgumentException("The content of URL should not be empty.", nameof(url));
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||
// Windows 必须设置 UseShellExecute = true 才能识别 URL
|
||||
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
|
||||
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
|
||||
Process.Start("xdg-open", url);
|
||||
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
|
||||
Process.Start("open", url);
|
||||
} else {
|
||||
throw new PlatformNotSupportedException("Not supported operating system.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Shared {
|
||||
|
||||
public static class Constant {
|
||||
public const string REPORT_BUG_URL = "https://github.com/yyc12345/BallanceTasToolbox/issues";
|
||||
|
||||
// YYC MARK:
|
||||
// TAS usually used FPS is 132 or 264.
|
||||
public const uint DEFAULT_FPS = 264;
|
||||
|
||||
public const uint DEFAULT_NEW_COUNT = 10000;
|
||||
public const uint DEFAULT_INSERT_COUNT = 100;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,33 +5,71 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Views {
|
||||
namespace BallanceTasEditor.Frontend.Shared {
|
||||
|
||||
public class DialogService : ViewModels.IDialogService {
|
||||
public interface IDialogService {
|
||||
NewFileDialogResult? ShowNewFileDialog();
|
||||
OpenFileDialogResult? ShowOpenFileDialog();
|
||||
void ShowOpenFileFailedDialog(Exception e);
|
||||
SaveFileDialogResult? ShowSaveFileDialog();
|
||||
void ShowSaveFileFailedDialog(Exception e);
|
||||
bool ShowConfirmCloseFileDialog(string message);
|
||||
bool ShowConfirmExitWhenOpeningFileDialog();
|
||||
bool ShowFileChangedDialog();
|
||||
GotoDialogResult? ShowGotoDialog();
|
||||
EditFpsDialogResult? ShowEditFpsDialog();
|
||||
AddFrameDialogResult? ShowAddFrameDialog();
|
||||
PreferenceDialogResult? ShowPreferenceDialog();
|
||||
void ShowManuallyReportBugDialog();
|
||||
void ShowAboutDialog();
|
||||
}
|
||||
|
||||
public record NewFileDialogResult {
|
||||
public required uint Fps { get; init; }
|
||||
public required int Count { get; init; }
|
||||
}
|
||||
|
||||
public record OpenFileDialogResult {
|
||||
public required string Path { get; init; }
|
||||
}
|
||||
|
||||
public record SaveFileDialogResult {
|
||||
public required string Path { get; init; }
|
||||
}
|
||||
|
||||
public record GotoDialogResult { }
|
||||
|
||||
public record EditFpsDialogResult { }
|
||||
|
||||
public record AddFrameDialogResult { }
|
||||
|
||||
public record PreferenceDialogResult { }
|
||||
|
||||
public class DialogService : IDialogService {
|
||||
public DialogService(Window parent) {
|
||||
m_Parent = parent;
|
||||
}
|
||||
|
||||
private readonly Window m_Parent;
|
||||
|
||||
public ViewModels.NewFileDialogResult? ShowNewFileDialog() {
|
||||
var dialog = new NewFileDialog();
|
||||
public NewFileDialogResult? ShowNewFileDialog() {
|
||||
var dialog = new Views.NewFileDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.NewFileDialogResult() { Count = 0, Fps = 60 };
|
||||
return new NewFileDialogResult() { Count = 0, Fps = 60 };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ViewModels.OpenFileDialogResult? ShowOpenFileDialog() {
|
||||
public OpenFileDialogResult? ShowOpenFileDialog() {
|
||||
Microsoft.Win32.OpenFileDialog op = new Microsoft.Win32.OpenFileDialog();
|
||||
op.RestoreDirectory = true;
|
||||
op.Multiselect = false;
|
||||
op.Filter = "TAS file(*.tas)|*.tas|All file(*.*)|*.*";
|
||||
if (op.ShowDialog() is true) {
|
||||
return new ViewModels.OpenFileDialogResult() { Path = op.FileName };
|
||||
return new OpenFileDialogResult() { Path = op.FileName };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -43,12 +81,12 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
public ViewModels.SaveFileDialogResult? ShowSaveFileDialog() {
|
||||
public SaveFileDialogResult? ShowSaveFileDialog() {
|
||||
Microsoft.Win32.SaveFileDialog op = new Microsoft.Win32.SaveFileDialog();
|
||||
op.RestoreDirectory = true;
|
||||
op.Filter = "TAS file(*.tas)|*.tas|All file(*.*)|*.*";
|
||||
if (op.ShowDialog() is true) {
|
||||
return new ViewModels.SaveFileDialogResult() { Path = op.FileName };
|
||||
return new SaveFileDialogResult() { Path = op.FileName };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -85,55 +123,62 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
return rv == MessageBoxResult.Yes;
|
||||
}
|
||||
|
||||
public ViewModels.GotoDialogResult? ShowGotoDialog() {
|
||||
var dialog = new GotoDialog();
|
||||
public GotoDialogResult? ShowGotoDialog() {
|
||||
var dialog = new Views.GotoDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.GotoDialogResult();
|
||||
return new GotoDialogResult();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ViewModels.EditFpsDialogResult? ShowEditFpsDialog() {
|
||||
var dialog = new EditFpsDialog();
|
||||
public EditFpsDialogResult? ShowEditFpsDialog() {
|
||||
var dialog = new Views.EditFpsDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.EditFpsDialogResult();
|
||||
return new EditFpsDialogResult();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ViewModels.AddFrameDialogResult? ShowAddFrameDialog() {
|
||||
var dialog = new AddFrameDialog();
|
||||
public AddFrameDialogResult? ShowAddFrameDialog() {
|
||||
var dialog = new Views.AddFrameDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.AddFrameDialogResult();
|
||||
return new AddFrameDialogResult();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ViewModels.PreferenceDialogResult? ShowPreferenceDialog() {
|
||||
var dialog = new PreferenceDialog();
|
||||
public PreferenceDialogResult? ShowPreferenceDialog() {
|
||||
var dialog = new Views.PreferenceDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.PreferenceDialogResult();
|
||||
return new PreferenceDialogResult();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowManuallyReportBugDialog() {
|
||||
MessageBox.Show($"We can not open browser automatically for you. Please visit {Shared.Constant.REPORT_BUG_URL} manually to report bug.",
|
||||
"Can not Open Browser",
|
||||
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
public void ShowAboutDialog() {
|
||||
var dialog = new AboutDialog();
|
||||
var dialog = new Views.AboutDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Shared {
|
||||
|
||||
/// <summary>
|
||||
/// The delegate used for view model requesting closing view window (non-modal window).
|
||||
/// </summary>
|
||||
public delegate void RequestCloseWindowEventHandler();
|
||||
|
||||
/// <summary>
|
||||
/// The delegate used for view model requesting closing view dialog (modal window).
|
||||
/// </summary>
|
||||
public delegate void RequestCloseDialogEventHandler(RequestCloseDialogEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// The payload passed when requesting closing view dialog (modal window).
|
||||
/// </summary>
|
||||
public record RequestCloseDialogEventArgs {
|
||||
/// <summary>
|
||||
/// True if we want to close windows by clicking Ok button, otherwise false.
|
||||
/// </summary>
|
||||
public required bool Result { get; init; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
public partial class AboutDialog : ObservableObject {
|
||||
|
||||
public AboutDialog() { }
|
||||
|
||||
[RelayCommand]
|
||||
private void Ok() {
|
||||
OnRequestCloseDialog(true);
|
||||
}
|
||||
|
||||
public event Shared.RequestCloseDialogEventHandler? RequestCloseDialog;
|
||||
|
||||
private void OnRequestCloseDialog(bool result) {
|
||||
RequestCloseDialog?.Invoke(new Shared.RequestCloseDialogEventArgs { Result = result });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
public partial class AddFrameDialog : ObservableObject {
|
||||
public AddFrameDialog() {
|
||||
Count = Shared.Constant.DEFAULT_INSERT_COUNT.ToString();
|
||||
Fps = Shared.Constant.DEFAULT_FPS.ToString();
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanOk))]
|
||||
private void Ok() {
|
||||
OnRequestCloseDialog(true);
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(OkCommand))]
|
||||
private string count;
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(OkCommand))]
|
||||
private string fps;
|
||||
|
||||
private bool CanOk() {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Cancel() {
|
||||
OnRequestCloseDialog(false);
|
||||
}
|
||||
|
||||
|
||||
public event Shared.RequestCloseDialogEventHandler? RequestCloseDialog;
|
||||
|
||||
private void OnRequestCloseDialog(bool result) {
|
||||
RequestCloseDialog?.Invoke(new Shared.RequestCloseDialogEventArgs { Result = result });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
public partial class EditFpsDialog : ObservableObject {
|
||||
public EditFpsDialog() {
|
||||
Fps = Shared.Constant.DEFAULT_FPS.ToString();
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(OkCommand))]
|
||||
private string fps;
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanOk))]
|
||||
private void Ok() {
|
||||
OnRequestCloseDialog(true);
|
||||
}
|
||||
|
||||
private bool CanOk() {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Cancel() {
|
||||
OnRequestCloseDialog(false);
|
||||
}
|
||||
|
||||
|
||||
public event Shared.RequestCloseDialogEventHandler? RequestCloseDialog;
|
||||
|
||||
private void OnRequestCloseDialog(bool result) {
|
||||
RequestCloseDialog?.Invoke(new Shared.RequestCloseDialogEventArgs { Result = result });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
public partial class GotoDialog : ObservableObject {
|
||||
public GotoDialog() {
|
||||
Index = 0.ToString();
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(OkCommand))]
|
||||
private string index;
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanOk))]
|
||||
private void Ok() {
|
||||
OnRequestCloseDialog(true);
|
||||
}
|
||||
|
||||
private bool CanOk() {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Cancel() {
|
||||
OnRequestCloseDialog(false);
|
||||
}
|
||||
|
||||
|
||||
public event Shared.RequestCloseDialogEventHandler? RequestCloseDialog;
|
||||
|
||||
private void OnRequestCloseDialog(bool result) {
|
||||
RequestCloseDialog?.Invoke(new Shared.RequestCloseDialogEventArgs { Result = result });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
|
||||
public interface IDialogService {
|
||||
NewFileDialogResult? ShowNewFileDialog();
|
||||
OpenFileDialogResult? ShowOpenFileDialog();
|
||||
void ShowOpenFileFailedDialog(Exception e);
|
||||
SaveFileDialogResult? ShowSaveFileDialog();
|
||||
void ShowSaveFileFailedDialog(Exception e);
|
||||
bool ShowConfirmCloseFileDialog(string message);
|
||||
bool ShowConfirmExitWhenOpeningFileDialog();
|
||||
bool ShowFileChangedDialog();
|
||||
GotoDialogResult? ShowGotoDialog();
|
||||
EditFpsDialogResult? ShowEditFpsDialog();
|
||||
AddFrameDialogResult? ShowAddFrameDialog();
|
||||
PreferenceDialogResult? ShowPreferenceDialog();
|
||||
void ShowAboutDialog();
|
||||
}
|
||||
|
||||
public record NewFileDialogResult {
|
||||
public required uint Fps { get; init; }
|
||||
public required int Count { get; init; }
|
||||
}
|
||||
|
||||
public record OpenFileDialogResult {
|
||||
public required string Path { get; init; }
|
||||
}
|
||||
|
||||
public record SaveFileDialogResult {
|
||||
public required string Path { get; init; }
|
||||
}
|
||||
|
||||
public record GotoDialogResult { }
|
||||
|
||||
public record EditFpsDialogResult { }
|
||||
|
||||
public record AddFrameDialogResult { }
|
||||
|
||||
public record PreferenceDialogResult { }
|
||||
|
||||
|
||||
}
|
||||
@@ -2,20 +2,23 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
public partial class MainWindow : ObservableObject {
|
||||
public MainWindow(IDialogService dialogService) {
|
||||
public MainWindow(Shared.IDialogService dialogService) {
|
||||
m_DialogService = dialogService;
|
||||
|
||||
this.TasFile = null;
|
||||
this.TasFilePath = null;
|
||||
}
|
||||
|
||||
private IDialogService m_DialogService;
|
||||
private Shared.IDialogService m_DialogService;
|
||||
|
||||
#region File Operation
|
||||
|
||||
@@ -134,6 +137,40 @@ namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
|
||||
#endregion
|
||||
|
||||
#region Exit Stuff
|
||||
|
||||
[RelayCommand]
|
||||
private void Exit() {
|
||||
// TODO
|
||||
OnRequestCloseWindow();
|
||||
}
|
||||
|
||||
public event Shared.RequestCloseWindowEventHandler? RequestCloseWindow;
|
||||
|
||||
private void OnRequestCloseWindow() {
|
||||
RequestCloseWindow?.Invoke();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Help Menu
|
||||
|
||||
[RelayCommand]
|
||||
private void ReportBug() {
|
||||
try {
|
||||
Shared.BrowserHelper.OpenInDefaultBrowser(Shared.Constant.REPORT_BUG_URL);
|
||||
} catch (Exception) {
|
||||
m_DialogService.ShowManuallyReportBugDialog();
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void About() {
|
||||
m_DialogService.ShowAboutDialog();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI Only
|
||||
|
||||
public string WindowTitle {
|
||||
|
||||
@@ -9,11 +9,10 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
|
||||
public partial class NewFileDialog : ObservableValidator {
|
||||
public partial class NewFileDialog : ObservableObject {
|
||||
public NewFileDialog() {
|
||||
Count = 10000.ToString();
|
||||
// 132 or 264
|
||||
Fps = 264.ToString();
|
||||
Count = Shared.Constant.DEFAULT_NEW_COUNT.ToString();
|
||||
Fps = Shared.Constant.DEFAULT_FPS.ToString();
|
||||
}
|
||||
|
||||
// YYC MARK:
|
||||
@@ -39,33 +38,49 @@ namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
// 就直接把string绑定到TextBox.Text上,然后再辅以我自己定义的一套可复用验证逻辑。
|
||||
|
||||
[ObservableProperty]
|
||||
//[CustomValidation(typeof(NewFileDialog), nameof(ValidateCount))]
|
||||
[NotifyCanExecuteChangedFor(nameof(OkCommand))]
|
||||
private string count;
|
||||
|
||||
[ObservableProperty]
|
||||
//[CustomValidation(typeof(NewFileDialog), nameof(ValidateFps))]
|
||||
[NotifyCanExecuteChangedFor(nameof(OkCommand))]
|
||||
private string fps;
|
||||
|
||||
//public static ValidationResult ValidateCount(string count, ValidationContext context) {
|
||||
// return CountValidator.Instance.Validate(count);
|
||||
//}
|
||||
//public static ValidationResult ValidateFps(string fps, ValidationContext context) {
|
||||
// return FpsValidator.Instance.Validate(fps);
|
||||
//}
|
||||
//[ObservableProperty]
|
||||
////[CustomValidation(typeof(NewFileDialog), nameof(ValidateCount))]
|
||||
//[NotifyCanExecuteChangedFor(nameof(OkCommand))]
|
||||
//private string count;
|
||||
|
||||
//[ObservableProperty]
|
||||
////[CustomValidation(typeof(NewFileDialog), nameof(ValidateFps))]
|
||||
//[NotifyCanExecuteChangedFor(nameof(OkCommand))]
|
||||
//private string fps;
|
||||
|
||||
////public static ValidationResult ValidateCount(string count, ValidationContext context) {
|
||||
//// return CountValidator.Instance.Validate(count);
|
||||
////}
|
||||
////public static ValidationResult ValidateFps(string fps, ValidationContext context) {
|
||||
//// return FpsValidator.Instance.Validate(fps);
|
||||
////}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanOk))]
|
||||
private void Ok() {
|
||||
|
||||
OnRequestCloseDialog(true);
|
||||
}
|
||||
|
||||
private bool CanOk() {
|
||||
return !HasErrors;
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Cancel() {
|
||||
OnRequestCloseDialog(false);
|
||||
}
|
||||
|
||||
|
||||
public event Shared.RequestCloseDialogEventHandler? RequestCloseDialog;
|
||||
|
||||
private void OnRequestCloseDialog(bool result) {
|
||||
RequestCloseDialog?.Invoke(new Shared.RequestCloseDialogEventArgs { Result = result});
|
||||
}
|
||||
|
||||
//public NewFileDialogResult ToResult() {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
public partial class PreferenceDialog : ObservableObject {
|
||||
public PreferenceDialog() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanOk))]
|
||||
private void Ok() {
|
||||
OnRequestCloseDialog(true);
|
||||
}
|
||||
|
||||
private bool CanOk() {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Cancel() {
|
||||
OnRequestCloseDialog(false);
|
||||
}
|
||||
|
||||
|
||||
public event Shared.RequestCloseDialogEventHandler? RequestCloseDialog;
|
||||
|
||||
private void OnRequestCloseDialog(bool result) {
|
||||
RequestCloseDialog?.Invoke(new Shared.RequestCloseDialogEventArgs { Result = result });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BallanceTasEditor.Frontend.Views"
|
||||
xmlns:vm="clr-namespace:BallanceTasEditor.Frontend.ViewModels"
|
||||
d:DataContext="{d:DesignInstance vm:AboutDialog}"
|
||||
mc:Ignorable="d" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" ShowInTaskbar="False"
|
||||
Title="About Ballance TAS Editor" Width="340" Height="480" Icon="/Frontend/Assets/About.ico">
|
||||
<Grid>
|
||||
@@ -24,7 +26,7 @@
|
||||
<!-- 详情(版权信息等) -->
|
||||
<TextBox Grid.Row="3" IsReadOnly="True" TextWrapping="Wrap" Margin="10"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
Text="Copyright © 2021-2025 yyc12345. All rights reserved.
|
||||
Text="Copyright © 2021-2026 yyc12345. All rights reserved.
|
||||
|
||||
Program: yyc12345
|
||||
Icon design: plAer_2
|
||||
@@ -33,6 +35,6 @@ Version: 1.2 stable
|
||||
Build Date: October 21, 2025 "/>
|
||||
|
||||
<!-- 确认按钮 -->
|
||||
<Button Grid.Row="4" Content="OK" Margin="10" HorizontalAlignment="Center" Style="{StaticResource OkButtonStyle}" IsDefault="True"/>
|
||||
<Button Grid.Row="4" Content="OK" Margin="10" HorizontalAlignment="Center" Style="{StaticResource OkButtonStyle}" IsDefault="True" Command="{Binding OkCommand}"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -19,6 +19,15 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
public partial class AboutDialog : Window {
|
||||
public AboutDialog() {
|
||||
InitializeComponent();
|
||||
|
||||
var vm = new ViewModels.AboutDialog();
|
||||
vm.RequestCloseDialog += ViewModel_RequestCloseDialog;
|
||||
this.DataContext = vm;
|
||||
}
|
||||
|
||||
private void ViewModel_RequestCloseDialog(Shared.RequestCloseDialogEventArgs e) {
|
||||
this.DialogResult = e.Result;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BallanceTasEditor.Frontend.Views"
|
||||
xmlns:vm="clr-namespace:BallanceTasEditor.Frontend.ViewModels"
|
||||
d:DataContext="{d:DesignInstance vm:AddFrameDialog}"
|
||||
mc:Ignorable="d" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" ShowInTaskbar="False"
|
||||
Title="Add Frame" Height="250" Width="400" Icon="/Frontend/Assets/AddFrame.ico">
|
||||
<Grid>
|
||||
@@ -51,8 +53,10 @@
|
||||
</Grid>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Right" Margin="10">
|
||||
<Button Content="OK" Margin="5" Style="{StaticResource OkButtonStyle}" IsDefault="True"/>
|
||||
<Button Content="Cancel" Margin="5" Style="{StaticResource CancelButtonStyle}"/>
|
||||
<Button Content="OK" Margin="5" Style="{StaticResource OkButtonStyle}" IsDefault="True"
|
||||
Command="{Binding OkCommand}"/>
|
||||
<Button Content="Cancel" Margin="5" Style="{StaticResource CancelButtonStyle}"
|
||||
Command="{Binding CancelCommand}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -19,6 +19,14 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
public partial class AddFrameDialog : Window {
|
||||
public AddFrameDialog() {
|
||||
InitializeComponent();
|
||||
|
||||
var vm = new ViewModels.AddFrameDialog();
|
||||
vm.RequestCloseDialog += ViewModel_RequestCloseDialog;
|
||||
this.DataContext = vm;
|
||||
}
|
||||
private void ViewModel_RequestCloseDialog(Shared.RequestCloseDialogEventArgs e) {
|
||||
this.DialogResult = e.Result;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BallanceTasEditor.Frontend.Views"
|
||||
xmlns:vm="clr-namespace:BallanceTasEditor.Frontend.ViewModels"
|
||||
d:DataContext="{d:DesignInstance vm:EditFpsDialog}"
|
||||
mc:Ignorable="d" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" ShowInTaskbar="False"
|
||||
Title="Edit FPS" Height="220" Width="400" Icon="/Frontend/Assets/SetFps.ico">
|
||||
<Grid>
|
||||
@@ -46,8 +48,10 @@
|
||||
</Grid>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Right" Margin="10">
|
||||
<Button Content="OK" Margin="5" Style="{StaticResource OkButtonStyle}" IsDefault="True"/>
|
||||
<Button Content="Cancel" Margin="5" Style="{StaticResource CancelButtonStyle}"/>
|
||||
<Button Content="OK" Margin="5" Style="{StaticResource OkButtonStyle}" IsDefault="True"
|
||||
Command="{Binding OkCommand}"/>
|
||||
<Button Content="Cancel" Margin="5" Style="{StaticResource CancelButtonStyle}"
|
||||
Command="{Binding CancelCommand}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -19,6 +19,15 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
public partial class EditFpsDialog : Window {
|
||||
public EditFpsDialog() {
|
||||
InitializeComponent();
|
||||
|
||||
var vm = new ViewModels.EditFpsDialog();
|
||||
vm.RequestCloseDialog += ViewModel_RequestCloseDialog;
|
||||
this.DataContext = vm;
|
||||
}
|
||||
|
||||
private void ViewModel_RequestCloseDialog(Shared.RequestCloseDialogEventArgs e) {
|
||||
this.DialogResult = e.Result;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BallanceTasEditor.Frontend.Views"
|
||||
xmlns:vm="clr-namespace:BallanceTasEditor.Frontend.ViewModels"
|
||||
d:DataContext="{d:DesignInstance vm:GotoDialog}"
|
||||
mc:Ignorable="d" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" ShowInTaskbar="False"
|
||||
Title="Goto..." Height="180" Width="400" Icon="/Frontend/Assets/Goto.ico">
|
||||
<Grid>
|
||||
@@ -26,8 +28,10 @@
|
||||
</Grid>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="2" HorizontalAlignment="Right" Margin="10">
|
||||
<Button Content="OK" Margin="5" Style="{StaticResource OkButtonStyle}" IsDefault="True"/>
|
||||
<Button Content="Cancel" Margin="5" Style="{StaticResource CancelButtonStyle}"/>
|
||||
<Button Content="OK" Margin="5" Style="{StaticResource OkButtonStyle}" IsDefault="True"
|
||||
Command="{Binding OkCommand}"/>
|
||||
<Button Content="Cancel" Margin="5" Style="{StaticResource CancelButtonStyle}"
|
||||
Command="{Binding CancelCommand}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -19,6 +19,15 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
public partial class GotoDialog : Window {
|
||||
public GotoDialog() {
|
||||
InitializeComponent();
|
||||
|
||||
var vm = new ViewModels.GotoDialog();
|
||||
vm.RequestCloseDialog += ViewModel_RequestCloseDialog;
|
||||
this.DataContext = vm;
|
||||
}
|
||||
|
||||
private void ViewModel_RequestCloseDialog(Shared.RequestCloseDialogEventArgs e) {
|
||||
this.DialogResult = e.Result;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<MenuItem Header="Save File then _Run Game" Icon="{StaticResource IconSaveFileThenRunGame}" InputGestureText="B"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Close File" Icon="{StaticResource IconCloseFile}" Command="{Binding CloseFileCommand}"/>
|
||||
<MenuItem Header="Exit" Icon="{StaticResource IconExit}"/>
|
||||
<MenuItem Header="Exit" Icon="{StaticResource IconExit}" Command="{Binding ExitCommand}"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Edit" Padding="5">
|
||||
<MenuItem Header="_Undo" Icon="{StaticResource IconUndo}" InputGestureText="Ctrl+Z"/>
|
||||
@@ -77,8 +77,8 @@
|
||||
<MenuItem Header="Preference" Icon="{StaticResource IconPreference}" InputGestureText="Ctrl+P"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Help" Padding="5">
|
||||
<MenuItem Header="Report Bug" Icon="{StaticResource IconReportBug}"/>
|
||||
<MenuItem Header="About" Icon="{StaticResource IconAbout}"/>
|
||||
<MenuItem Header="Report Bug" Icon="{StaticResource IconReportBug}" Command="{Binding ReportBugCommand}"/>
|
||||
<MenuItem Header="About" Icon="{StaticResource IconAbout}" Command="{Binding AboutCommand}"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
|
||||
@@ -20,9 +20,15 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
public partial class MainWindow : Window {
|
||||
public MainWindow() {
|
||||
InitializeComponent();
|
||||
var dialogService = new DialogService(this);
|
||||
this.DataContext = new ViewModels.MainWindow(dialogService);
|
||||
|
||||
var dialogService = new Shared.DialogService(this);
|
||||
var vm = new ViewModels.MainWindow(dialogService);
|
||||
vm.RequestCloseWindow += ViewModel_RequestCloseWindow;
|
||||
this.DataContext = vm;
|
||||
}
|
||||
|
||||
private void ViewModel_RequestCloseWindow() {
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,15 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
public partial class NewFileDialog : Window {
|
||||
public NewFileDialog() {
|
||||
InitializeComponent();
|
||||
this.DataContext = new ViewModels.NewFileDialog();
|
||||
|
||||
var vm = new ViewModels.NewFileDialog();
|
||||
vm.RequestCloseDialog += ViewModel_RequestCloseDialog;
|
||||
this.DataContext = vm;
|
||||
}
|
||||
|
||||
private void ViewModel_RequestCloseDialog(Shared.RequestCloseDialogEventArgs e) {
|
||||
this.DialogResult = e.Result;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BallanceTasEditor.Frontend.Views"
|
||||
xmlns:vm="clr-namespace:BallanceTasEditor.Frontend.ViewModels"
|
||||
xmlns:styles="clr-namespace:BallanceTasEditor.Frontend.Styles"
|
||||
d:DataContext="{d:DesignInstance vm:PreferenceDialog}"
|
||||
mc:Ignorable="d" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" ShowInTaskbar="False"
|
||||
Title="Editor Preference" Height="450" Width="400" Icon="/Frontend/Assets/Preference.ico">
|
||||
<Grid>
|
||||
@@ -57,8 +59,10 @@
|
||||
</ScrollViewer>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Right" Margin="10">
|
||||
<Button Content="OK" Margin="5" Style="{StaticResource OkButtonStyle}" IsDefault="True"/>
|
||||
<Button Content="Cancel" Margin="5" Style="{StaticResource CancelButtonStyle}"/>
|
||||
<Button Content="OK" Margin="5" Style="{StaticResource OkButtonStyle}" IsDefault="True"
|
||||
Command="{Binding OkCommand}"/>
|
||||
<Button Content="Cancel" Margin="5" Style="{StaticResource CancelButtonStyle}"
|
||||
Command="{Binding CancelCommand}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -19,6 +19,15 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
public partial class PreferenceDialog : Window {
|
||||
public PreferenceDialog() {
|
||||
InitializeComponent();
|
||||
|
||||
var vm = new ViewModels.PreferenceDialog();
|
||||
vm.RequestCloseDialog += ViewModel_RequestCloseDialog;
|
||||
this.DataContext = vm;
|
||||
}
|
||||
|
||||
private void ViewModel_RequestCloseDialog(Shared.RequestCloseDialogEventArgs e) {
|
||||
this.DialogResult = e.Result;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user