Merge branch 'LorisYounger:main' into main

This commit is contained in:
Dragon Taki 2024-01-14 08:19:36 +08:00 committed by GitHub
commit 1631c35ef5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1621 additions and 335 deletions

View File

@ -35,6 +35,8 @@ using Line = LinePutScript.Line;
using static VPet_Simulator.Windows.Interface.ExtensionFunction; using static VPet_Simulator.Windows.Interface.ExtensionFunction;
using Image = System.Windows.Controls.Image; using Image = System.Windows.Controls.Image;
using VPet.Solution;
namespace VPet_Simulator.Windows namespace VPet_Simulator.Windows
{ {
public partial class MainWindow : IMainWindow public partial class MainWindow : IMainWindow

View File

@ -128,6 +128,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\VPet-Simulator.Core\VPet-Simulator.Core.csproj" /> <ProjectReference Include="..\VPet-Simulator.Core\VPet-Simulator.Core.csproj" />
<ProjectReference Include="..\VPet-Simulator.Windows.Interface\VPet-Simulator.Windows.Interface.csproj" /> <ProjectReference Include="..\VPet-Simulator.Windows.Interface\VPet-Simulator.Windows.Interface.csproj" />
<ProjectReference Include="..\VPet.Solution\VPet.Solution.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Properties\Settings.Designer.cs"> <Compile Update="Properties\Settings.Designer.cs">

View File

@ -699,6 +699,7 @@ namespace VPet_Simulator.Windows
btn_r_save.IsEnabled = true; btn_r_save.IsEnabled = true;
pb_r_genRank.Visibility = Visibility.Collapsed; pb_r_genRank.Visibility = Visibility.Collapsed;
Width = 800; Width = 800;
Height = 800;
}); });
} }
private string px_tocm(long px, out string cm) private string px_tocm(long px, out string cm)

View File

@ -2,7 +2,7 @@
/// food:|name#五仁月饼:|type#Meal:|Exp#100:|Strength#80:|StrengthDrink#-6:|StrengthFood#160:|Likability#1:|Health#5:|Feeling#0:|price#38:|graph#eat:|desc#举头望明月,低头思故乡。无论身在何处,离家多远,家人在不在身边,心情好不好,萝莉丝都为你做了五仁月饼,快说谢谢萝莉丝。:| /// food:|name#五仁月饼:|type#Meal:|Exp#100:|Strength#80:|StrengthDrink#-6:|StrengthFood#160:|Likability#1:|Health#5:|Feeling#0:|price#38:|graph#eat:|desc#举头望明月,低头思故乡。无论身在何处,离家多远,家人在不在身边,心情好不好,萝莉丝都为你做了五仁月饼,快说谢谢萝莉丝。:|
/// food:|name#巧克力花生月饼:|type#Functional:|Exp#400:|Strength#20:|StrengthDrink#0:|StrengthFood#40:|Likability#2:|Health#5:|Feeling#20:|price#62:|graph#eat:|desc#明月几时有,把酒问青天。无论考的如何,作业有多少,老师怎么说,家长怎么批评,萝莉丝都为你做了巧克力花生月饼,快说谢谢萝莉丝。:| /// food:|name#巧克力花生月饼:|type#Functional:|Exp#400:|Strength#20:|StrengthDrink#0:|StrengthFood#40:|Likability#2:|Health#5:|Feeling#20:|price#62:|graph#eat:|desc#明月几时有,把酒问青天。无论考的如何,作业有多少,老师怎么说,家长怎么批评,萝莉丝都为你做了巧克力花生月饼,快说谢谢萝莉丝。:|
food:|name#圣诞帽:|type#Gift:|Exp#200:|Likability#4:|Health#5:|Feeling#50:|price#40.0:|graph#gift:|desc#圣诞帽_giftintor:| food:|name#圣诞帽:|type#Gift:|Exp#200:|Likability#4:|Health#5:|Feeling#50:|price#45.0:|graph#gift:|desc#圣诞帽_giftintor:|
food:|name#礼物盒子:|type#Gift:|Exp#1000:|Likability#5:|Feeling#100:|price#150.0:|graph#gift:|desc#礼物盒子_giftintor:| food:|name#礼物盒子:|type#Gift:|Exp#1000:|Likability#5:|Feeling#100:|price#150.0:|graph#gift:|desc#礼物盒子_giftintor:|
food:|name#糖果棒:|type#Snack:|Exp#200:|Strength#40:|StrengthFood#40:|Likability#2:|Feeling#40:|price#35:|graph#eat:|desc#糖果棒_giftintor:| food:|name#糖果棒:|type#Snack:|Exp#200:|Strength#40:|StrengthFood#40:|Likability#2:|Feeling#40:|price#35:|graph#eat:|desc#糖果棒_giftintor:|
food:|name#圣诞草莓奶茶:|type#Drink:|Exp#200:|StrengthDrink#80:|Likability#2:|Feeling#60:|price#35:|graph#drink:|desc#圣诞草莓奶茶_giftintor:| food:|name#圣诞草莓奶茶:|type#Drink:|Exp#200:|StrengthDrink#80:|Likability#2:|Feeling#60:|price#35:|graph#drink:|desc#圣诞草莓奶茶_giftintor:|

View File

@ -0,0 +1,226 @@
using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VPet_Simulator.Windows.Interface;
namespace VPet.Solution.Models.SaveViewer;
/// <summary>
/// 存档模型
/// </summary>
public class SaveModel : ObservableClass<SaveModel>
{
/// <summary>
/// 名称
/// </summary>
[ReflectionPropertyIgnore]
public string Name { get; set; }
/// <summary>
/// 文件路径
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 统计数据
/// </summary>
public ObservableCollection<StatisticDataModel> Statistics { get; set; } = new();
/// <summary>
/// 是损坏的
/// </summary>
public bool IsDamaged { get; set; }
#region DateSaved
private DateTime _dateSaved;
public DateTime DateSaved
{
get => _dateSaved;
set => SetProperty(ref _dateSaved, value);
}
#endregion
#region PetName
private string _petName;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Name))]
public string PetName
{
get => _petName;
set => SetProperty(ref _petName, value);
}
#endregion
#region Level
private int _level;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Level))]
public int Level
{
get => _level;
set => SetProperty(ref _level, value);
}
#endregion
#region Money
private double _money = 100;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Money))]
public double Money
{
get => _money;
set => SetProperty(ref _money, value);
}
#endregion
#region Exp
private double _exp = 0;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Exp))]
public double Exp
{
get => _exp;
set => SetProperty(ref _exp, value);
}
#endregion
#region Feeling
private double _feeling = 60;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Feeling))]
public double Feeling
{
get => _feeling;
set => SetProperty(ref _feeling, value);
}
#endregion
#region Health
private double _health = 100;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Health))]
public double Health
{
get => _health;
set => SetProperty(ref _health, value);
}
#endregion
#region Likability
private double _likability = 0;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Likability))]
public double Likability
{
get => _likability;
set => SetProperty(ref _likability, value);
}
#endregion
#region Mode
private VPet_Simulator.Core.GameSave.ModeType _mode;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Mode))]
public VPet_Simulator.Core.GameSave.ModeType Mode
{
get => _mode;
set => SetProperty(ref _mode, value);
}
#endregion
#region Strength
private double _strength = 100;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.Strength))]
public double Strength
{
get => _strength;
set => SetProperty(ref _strength, value);
}
#endregion
#region StrengthFood
private double _strengthFood = 100;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.StrengthFood))]
public double StrengthFood
{
get => _strengthFood;
set => SetProperty(ref _strengthFood, value);
}
#endregion
#region StrengthDrink
private double _strengthDrink = 100;
[ReflectionProperty(nameof(VPet_Simulator.Core.GameSave.StrengthDrink))]
public double StrengthDrink
{
get => _strengthDrink;
set => SetProperty(ref _strengthDrink, value);
}
#endregion
#region HashChecked
private bool _hashChecked;
/// <summary>
/// Hash已检查
/// </summary>
public bool HashChecked
{
get => _hashChecked;
set => SetProperty(ref _hashChecked, value);
}
#endregion
#region TotalTime
private long _totalTime;
/// <summary>
/// 游玩总时长
/// </summary>
public long TotalTime
{
get => _totalTime;
set => SetProperty(ref _totalTime, value);
}
#endregion
public SaveModel(string filePath, GameSave_v2 save)
{
Name = Path.GetFileNameWithoutExtension(filePath);
FilePath = filePath;
DateSaved = File.GetLastWriteTime(filePath);
LoadSave(save.GameSave);
if (save.Statistics.Data.TryGetValue("stat_total_time", out var time))
TotalTime = time.GetInteger64();
HashChecked = save.HashCheck;
foreach (var data in save.Statistics.Data)
{
Statistics.Add(
new()
{
Id = data.Key,
Name = data.Key.Translate(),
Value = data.Value
}
);
}
}
private void LoadSave(VPet_Simulator.Core.GameSave save)
{
ReflectionUtils.SetValue(save, this);
}
}

View File

@ -0,0 +1,46 @@
namespace VPet.Solution.Models.SaveViewer;
/// <summary>
/// 统计数据模型
/// </summary>
public class StatisticDataModel : ObservableClass<StatisticDataModel>
{
#region Id
private string _id;
/// <summary>
/// ID
/// </summary>
public string Id
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
#region Name
private string _name;
/// <summary>
/// 名称
/// </summary>
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
#region Value
private object _value;
/// <summary>
/// 值
/// </summary>
public object Value
{
get => _value;
set => SetProperty(ref _value, value);
}
#endregion
}

View File

@ -1,4 +1,6 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF;
using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Windows; using System.Windows;
@ -6,13 +8,14 @@ namespace VPet.Solution.Models.SettingEditor;
public class GraphicsSettingModel : ObservableClass<GraphicsSettingModel> public class GraphicsSettingModel : ObservableClass<GraphicsSettingModel>
{ {
#region #region ZoomLevel
private double _zoomLevel = 1; private double _zoomLevel = 1;
/// <summary> /// <summary>
/// 缩放倍率 /// 缩放倍率
/// </summary> /// </summary>
[DefaultValue(1)] [DefaultValue(1)]
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.ZoomLevel))]
public double ZoomLevel public double ZoomLevel
{ {
get => _zoomLevel; get => _zoomLevel;
@ -37,23 +40,29 @@ public class GraphicsSettingModel : ObservableClass<GraphicsSettingModel>
set => SetProperty(ref _zoomLevelMaximum, value); set => SetProperty(ref _zoomLevelMaximum, value);
} }
#endregion #endregion
#region Resolution
private int _resolution = 1000; private int _resolution = 1000;
/// <summary> /// <summary>
/// 桌宠图形渲染的分辨率,越高图形越清晰 /// 桌宠图形渲染的分辨率,越高图形越清晰
/// </summary> /// </summary>
[DefaultValue(1000)] [DefaultValue(1000)]
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Resolution))]
public int Resolution public int Resolution
{ {
get => _resolution; get => _resolution;
set => SetProperty(ref _resolution, value); set => SetProperty(ref _resolution, value);
} }
#endregion
#region IsBiggerScreen
private bool _isBiggerScreen; private bool _isBiggerScreen;
/// <summary> /// <summary>
/// 是否为更大的屏幕 /// 是否为更大的屏幕
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.IsBiggerScreen))]
public bool IsBiggerScreen public bool IsBiggerScreen
{ {
get => _isBiggerScreen; get => _isBiggerScreen;
@ -66,94 +75,125 @@ public class GraphicsSettingModel : ObservableClass<GraphicsSettingModel>
ZoomLevelMaximum = 3; ZoomLevelMaximum = 3;
} }
} }
#endregion
#region TopMost
private bool _topMost; private bool _topMost;
/// <summary> /// <summary>
/// 是否置于顶层 /// 是否置于顶层
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.TopMost))]
public bool TopMost public bool TopMost
{ {
get => _topMost; get => _topMost;
set => SetProperty(ref _topMost, value); set => SetProperty(ref _topMost, value);
} }
#endregion
#region HitThrough
private bool _hitThrough; private bool _hitThrough;
/// <summary> /// <summary>
/// 是否鼠标穿透 /// 是否鼠标穿透
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.HitThrough))]
public bool HitThrough public bool HitThrough
{ {
get => _hitThrough; get => _hitThrough;
set => SetProperty(ref _hitThrough, value); set => SetProperty(ref _hitThrough, value);
} }
#endregion
private string _language; #region Language
private string _language = Languages.First();
/// <summary> /// <summary>
/// 语言 /// 语言
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Language))]
public string Language public string Language
{ {
get => _language; get => _language;
set => SetProperty(ref _language, value); set => SetProperty(ref _language, value);
} }
public static ObservableCollection<string> Languages { get; } =
new() { "zh-Hans", "zh-Hant", "en" };
// NOTE: 实际上这里面并没有文化 new(LocalizeCore.AvailableCultures);
#endregion
#region Font
private string _font; private string _font;
/// <summary> /// <summary>
/// 字体 /// 字体
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Font))]
public string Font public string Font
{ {
get => _font; get => _font;
set => SetProperty(ref _font, value); set => SetProperty(ref _font, value);
} }
#endregion
#region Theme
private string _theme; private string _theme;
/// <summary> /// <summary>
/// 主题 /// 主题
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Theme))]
public string Theme public string Theme
{ {
get => _theme; get => _theme;
set => SetProperty(ref _theme, value); set => SetProperty(ref _theme, value);
} }
#endregion
#region StartUPBoot
private bool _startUPBoot; private bool _startUPBoot;
/// <summary> /// <summary>
/// 开机启动 /// 开机启动
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.StartUPBoot))]
public bool StartUPBoot public bool StartUPBoot
{ {
get => _startUPBoot; get => _startUPBoot;
set => SetProperty(ref _startUPBoot, value); set => SetProperty(ref _startUPBoot, value);
} }
#endregion
#region StartUPBootSteam
private bool _startUPBootSteam; private bool _startUPBootSteam;
/// <summary> /// <summary>
/// 开机启动 Steam /// 开机启动 Steam
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.StartUPBootSteam))]
public bool StartUPBootSteam public bool StartUPBootSteam
{ {
get => _startUPBootSteam; get => _startUPBootSteam;
set => SetProperty(ref _startUPBootSteam, value); set => SetProperty(ref _startUPBootSteam, value);
} }
#endregion
#region StartRecordLast
private bool _startRecordLast = true; private bool _startRecordLast = true;
/// <summary> /// <summary>
/// 是否记录游戏退出位置 /// 是否记录游戏退出位置
/// </summary> /// </summary>
[DefaultValue(true)] [DefaultValue(true)]
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.StartRecordLast))]
public bool StartRecordLast public bool StartRecordLast
{ {
get => _startRecordLast; get => _startRecordLast;
set => SetProperty(ref _startRecordLast, value); set => SetProperty(ref _startRecordLast, value);
} }
#endregion
//private Point _startRecordLastPoint; //private Point _startRecordLastPoint;
///// <summary> ///// <summary>
@ -165,26 +205,92 @@ public class GraphicsSettingModel : ObservableClass<GraphicsSettingModel>
// set => SetProperty(ref _startRecordLastPoint, value); // set => SetProperty(ref _startRecordLastPoint, value);
//} //}
#region StartRecordPoint
private ObservablePoint _startRecordPoint; private ObservablePoint _startRecordPoint;
/// <summary> /// <summary>
/// 设置中桌宠启动的位置 /// 设置中桌宠启动的位置
/// </summary> /// </summary>
[ReflectionPropertyInfo(typeof(ObservablePointToPointConverter))] [ReflectionProperty]
[ReflectionPropertyConverter(typeof(ObservablePointToPointConverter))]
public ObservablePoint StartRecordPoint public ObservablePoint StartRecordPoint
{ {
get => _startRecordPoint; get => _startRecordPoint;
set => SetProperty(ref _startRecordPoint, value); set => SetProperty(ref _startRecordPoint, value);
} }
#endregion
#region HideFromTaskControl
private bool _hideFromTaskControl; private bool _hideFromTaskControl;
/// <summary> /// <summary>
/// 在任务切换器(Alt+Tab)中隐藏窗口 /// 在任务切换器(Alt+Tab)中隐藏窗口
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.HideFromTaskControl))]
public bool HideFromTaskControl public bool HideFromTaskControl
{ {
get => _hideFromTaskControl; get => _hideFromTaskControl;
set => SetProperty(ref _hideFromTaskControl, value); set => SetProperty(ref _hideFromTaskControl, value);
} }
#endregion
#region MessageBarOutside
private bool _messageBarOutside;
/// <summary>
/// 消息框外置
/// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MessageBarOutside))]
public bool MessageBarOutside
{
get => _messageBarOutside;
set => SetProperty(ref _messageBarOutside, value);
}
#endregion
#region PetHelper
private bool _petHelper;
/// <summary>
/// 是否显示宠物帮助窗口
/// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetHelper))]
public bool PetHelper
{
get => _petHelper;
set => SetProperty(ref _petHelper, value);
}
#endregion
#region PetHelpLeft
private double _petHelpLeft;
// TODO 加入 PetHelpLeft
/// <summary>
/// 快捷穿透按钮X坐标
/// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetHelpLeft))]
public double PetHelpLeft
{
get => _petHelpLeft;
set => SetProperty(ref _petHelpLeft, value);
}
#endregion
#region PetHelpTop
private double _petHelpTop;
// TODO 加入 PetHelpTop
/// <summary>
/// 快捷穿透按钮Y坐标
/// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetHelpTop))]
public double PetHelpTop
{
get => _petHelpTop;
set => SetProperty(ref _petHelpTop, value);
}
#endregion
} }

View File

@ -1,251 +1,311 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using System.Collections.ObjectModel;
using System.ComponentModel;
using VPet_Simulator.Core; using VPet_Simulator.Core;
namespace VPet.Solution.Models.SettingEditor; namespace VPet.Solution.Models.SettingEditor;
public class InteractiveSettingModel : ObservableClass<InteractiveSettingModel> public class InteractiveSettingModel : ObservableClass<InteractiveSettingModel>
{ {
private string _petName; // NOTE: 这玩意其实在存档里 而不是设置里
//#region PetName
//private string _petName;
/// <summary> ///// <summary>
/// 宠物名称 ///// 宠物名称
/// </summary> ///// </summary>
public string PetName //[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetName))]
{ //public string PetName
get => _petName; //{
set => SetProperty(ref _petName, value); // get => _petName;
} // set => SetProperty(ref _petName, value);
//}
//#endregion
#region VoiceVolume
private double _voiceVolume; private double _voiceVolume;
/// <summary> /// <summary>
/// 播放声音大小 /// 播放声音大小
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.VoiceVolume))]
public double VoiceVolume public double VoiceVolume
{ {
get => _voiceVolume; get => _voiceVolume;
set => SetProperty(ref _voiceVolume, value); set => SetProperty(ref _voiceVolume, value);
} }
#endregion
#region EnableFunction
private bool _enableFunction;
/// <summary>
/// 启用计算等数据功能
/// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.EnableFunction))]
public bool EnableFunction
{
get => _enableFunction;
set => SetProperty(ref _enableFunction, value);
}
#endregion
#region CalFunState
private GameSave.ModeType _calFunState; private GameSave.ModeType _calFunState;
/// <summary> /// <summary>
/// 非计算模式下默认模式 /// 非计算模式下默认模式
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.CalFunState))]
public GameSave.ModeType CalFunState public GameSave.ModeType CalFunState
{ {
get => _calFunState; get => _calFunState;
set => SetProperty(ref _calFunState, value); set => SetProperty(ref _calFunState, value);
} }
private bool _petHelper; public ObservableCollection<GameSave.ModeType> ModeTypes { get; } =
new(Enum.GetValues(typeof(GameSave.ModeType)).Cast<GameSave.ModeType>());
/// <summary> #endregion
/// 是否显示宠物帮助窗口
/// </summary>
public bool PetHelper
{
get => _petHelper;
set => SetProperty(ref _petHelper, value);
}
#region LastCacheDate
private DateTime _lastCacheDate; private DateTime _lastCacheDate;
/// <summary> /// <summary>
/// 上次清理缓存日期 /// 上次清理缓存日期
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.LastCacheDate))]
public DateTime LastCacheDate public DateTime LastCacheDate
{ {
get => _lastCacheDate; get => _lastCacheDate;
set => SetProperty(ref _lastCacheDate, value); set => SetProperty(ref _lastCacheDate, value);
} }
#endregion
#region SaveTimes
private int _saveTimes; private int _saveTimes;
/// <summary> /// <summary>
/// 储存顺序次数 /// 储存顺序次数
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.SaveTimes))]
public int SaveTimes public int SaveTimes
{ {
get => _saveTimes; get => _saveTimes;
set => SetProperty(ref _saveTimes, value); set => SetProperty(ref _saveTimes, value);
} }
#endregion
#region PressLength
private int _pressLength; private int _pressLength;
/// <summary> /// <summary>
/// 按多久视为长按 单位毫秒 /// 按多久视为长按 单位毫秒
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PressLength))]
public int PressLength public int PressLength
{ {
get => _pressLength; get => _pressLength;
set => SetProperty(ref _pressLength, value); set => SetProperty(ref _pressLength, value);
} }
#endregion
#region InteractionCycle
private int _interactionCycle; private int _interactionCycle;
/// <summary> /// <summary>
/// 互动周期 /// 互动周期
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.InteractionCycle))]
public int InteractionCycle public int InteractionCycle
{ {
get => _interactionCycle; get => _interactionCycle;
set => SetProperty(ref _interactionCycle, value); set => SetProperty(ref _interactionCycle, value);
} }
#endregion
#region LogicInterval
private double _logicInterval; private double _logicInterval;
/// <summary> /// <summary>
/// 计算间隔 (秒) /// 计算间隔 (秒)
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.LogicInterval))]
public double LogicInterval public double LogicInterval
{ {
get => _logicInterval; get => _logicInterval;
set => SetProperty(ref _logicInterval, value); set => SetProperty(ref _logicInterval, value);
} }
#endregion
private double _petHelpLeft; #region AllowMove
/// <summary>
/// 计算间隔
/// </summary>
public double PetHelpLeft
{
get => _petHelpLeft;
set => SetProperty(ref _petHelpLeft, value);
}
private double _petHelpTop;
/// <summary>
/// 计算间隔
/// </summary>
public double PetHelpTop
{
get => _petHelpTop;
set => SetProperty(ref _petHelpTop, value);
}
private bool _allowMove; private bool _allowMove;
/// <summary> /// <summary>
/// 允许移动事件 /// 允许移动事件
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.AllowMove))]
public bool AllowMove public bool AllowMove
{ {
get => _allowMove; get => _allowMove;
set => SetProperty(ref _allowMove, value); set => SetProperty(ref _allowMove, value);
} }
#endregion
#region SmartMove
private bool _smartMove; private bool _smartMove;
/// <summary> /// <summary>
/// 智能移动 /// 智能移动
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.SmartMove))]
public bool SmartMove public bool SmartMove
{ {
get => _smartMove; get => _smartMove;
set => SetProperty(ref _smartMove, value); set => SetProperty(ref _smartMove, value);
} }
#endregion
private bool _enableFunction; #region SmartMoveInterval
private int _smartMoveInterval = 0;
/// <summary>
/// 启用计算等数据功能
/// </summary>
public bool EnableFunction
{
get => _enableFunction;
set => SetProperty(ref _enableFunction, value);
}
private int _smartMoveInterval;
/// <summary> /// <summary>
/// 智能移动周期 (秒) /// 智能移动周期 (秒)
/// </summary> /// </summary>
[DefaultValue(1)]
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.SmartMoveInterval))]
[ReflectionPropertyConverter(typeof(SecondToMinuteConverter))]
public int SmartMoveInterval public int SmartMoveInterval
{ {
get => _smartMoveInterval; get => _smartMoveInterval;
set => SetProperty(ref _smartMoveInterval, value); set => SetProperty(ref _smartMoveInterval, value);
} }
private bool _messageBarOutside; public static ObservableCollection<int> SmartMoveIntervals { get; } =
new() { 1, 2, 5, 10, 20, 30, 40, 50, 60 };
/// <summary> #endregion
/// 消息框外置
/// </summary>
public bool MessageBarOutside
{
get => _messageBarOutside;
set => SetProperty(ref _messageBarOutside, value);
}
#region PetGraph
private string _petGraph; private string _petGraph;
/// <summary> /// <summary>
/// 桌宠选择内容 /// 桌宠选择内容
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.PetGraph))]
public string PetGraph public string PetGraph
{ {
get => _petGraph; get => _petGraph;
set => SetProperty(ref _petGraph, value); set => SetProperty(ref _petGraph, value);
} }
#endregion
private double _musicCatch; #region MusicCatch
private int _musicCatch;
/// <summary> /// <summary>
/// 当实时播放音量达到该值时运行音乐动作 /// 当实时播放音量达到该值时运行音乐动作
/// </summary> /// </summary>
public double MusicCatch [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MusicCatch))]
[ReflectionPropertyConverter(typeof(DoubleToInt32Converter))]
public int MusicCatch
{ {
get => _musicCatch; get => _musicCatch;
set => SetProperty(ref _musicCatch, value); set => SetProperty(ref _musicCatch, value);
} }
#endregion
private double _musicMax; #region MusicMax
private int _musicMax;
/// <summary> /// <summary>
/// 当实时播放音量达到该值时运行特殊音乐动作 /// 当实时播放音量达到该值时运行特殊音乐动作
/// </summary> /// </summary>
public double MusicMax [ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MusicMax))]
[ReflectionPropertyConverter(typeof(DoubleToInt32Converter))]
public int MusicMax
{ {
get => _musicMax; get => _musicMax;
set => SetProperty(ref _musicMax, value); set => SetProperty(ref _musicMax, value);
} }
#endregion
#region AutoBuy
private bool _autoBuy; private bool _autoBuy;
// TODO 加入 AutoBuy
/// <summary> /// <summary>
/// 允许桌宠自动购买食品 /// 允许桌宠自动购买食品
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.AutoBuy))]
public bool AutoBuy public bool AutoBuy
{ {
get => _autoBuy; get => _autoBuy;
set => SetProperty(ref _autoBuy, value); set => SetProperty(ref _autoBuy, value);
} }
#endregion
#region AutoGift
private bool _autoGift; private bool _autoGift;
// TODO 加入 AutoGift
/// <summary> /// <summary>
/// 允许桌宠自动购买礼物 /// 允许桌宠自动购买礼物
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.AutoGift))]
public bool AutoGift public bool AutoGift
{ {
get => _autoGift; get => _autoGift;
set => SetProperty(ref _autoGift, value); set => SetProperty(ref _autoGift, value);
} }
#endregion
#region MoveAreaDefault
private bool _moveAreaDefault; private bool _moveAreaDefault;
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MoveAreaDefault))]
public bool MoveAreaDefault public bool MoveAreaDefault
{ {
get => _moveAreaDefault; get => _moveAreaDefault;
set => SetProperty(ref _moveAreaDefault, value); set => SetProperty(ref _moveAreaDefault, value);
} }
#endregion
#region MoveArea
private System.Drawing.Rectangle _moveArea; private System.Drawing.Rectangle _moveArea;
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.MoveArea))]
public System.Drawing.Rectangle MoveArea public System.Drawing.Rectangle MoveArea
{ {
get => _moveArea; get => _moveArea;
set => SetProperty(ref _moveArea, value); set => SetProperty(ref _moveArea, value);
} }
#endregion
}
public class SecondToMinuteConverter : ReflectionConverterBase<int, int>
{
public override int Convert(int sourceValue)
{
return sourceValue * 60;
}
public override int ConvertBack(int targetValue)
{
if (targetValue == 30)
return 1;
else
return targetValue / 60;
}
}
public class DoubleToInt32Converter : ReflectionConverterBase<int, double>
{
public override double Convert(int sourceValue)
{
return sourceValue;
}
public override int ConvertBack(double targetValue)
{
return System.Convert.ToInt32(targetValue);
}
} }

View File

@ -12,35 +12,26 @@ namespace VPet.Solution.Models.SettingEditor;
public class SettingModel : ObservableClass<SettingModel> public class SettingModel : ObservableClass<SettingModel>
{ {
private string _name;
/// <summary> /// <summary>
/// 名称 /// 名称
/// </summary> /// </summary>
public string Name public string Name { get; set; }
{
get => _name;
set => SetProperty(ref _name, value);
}
private string _filePath;
/// <summary> /// <summary>
/// 文件路径 /// 文件路径
/// </summary> /// </summary>
public string FilePath public string FilePath { get; set; }
{
get => _filePath;
set => SetProperty(ref _filePath, value);
}
#region GraphicsSetting
private GraphicsSettingModel _graphicsSetting; private GraphicsSettingModel _graphicsSetting;
public GraphicsSettingModel GraphicsSetting public GraphicsSettingModel GraphicsSetting
{ {
get => _graphicsSetting; get => _graphicsSetting;
set => SetProperty(ref _graphicsSetting, value); set => SetProperty(ref _graphicsSetting, value);
} }
#endregion
#region SystemSetting
private SystemSettingModel _systemSetting; private SystemSettingModel _systemSetting;
public SystemSettingModel SystemSetting public SystemSettingModel SystemSetting
@ -48,13 +39,16 @@ public class SettingModel : ObservableClass<SettingModel>
get => _systemSetting; get => _systemSetting;
set => SetProperty(ref _systemSetting, value); set => SetProperty(ref _systemSetting, value);
} }
#endregion
#region InteractiveSetting
private InteractiveSettingModel _interactiveSetting; private InteractiveSettingModel _interactiveSetting;
public InteractiveSettingModel InteractiveSetting public InteractiveSettingModel InteractiveSetting
{ {
get => _interactiveSetting; get => _interactiveSetting;
set => SetProperty(ref _interactiveSetting, value); set => SetProperty(ref _interactiveSetting, value);
} }
#endregion
private static HashSet<string> _settingProperties = private static HashSet<string> _settingProperties =
new(typeof(Setting).GetProperties().Select(p => p.Name)); new(typeof(Setting).GetProperties().Select(p => p.Name));
@ -63,27 +57,35 @@ public class SettingModel : ObservableClass<SettingModel>
private ReflectionOptions _saveReflectionOptions = new() { CheckValueEquals = true }; private ReflectionOptions _saveReflectionOptions = new() { CheckValueEquals = true };
public SettingModel()
: this(new("")) { }
public SettingModel(Setting setting) public SettingModel(Setting setting)
{ {
_setting = setting; _setting = setting;
GraphicsSetting = LoadGraphicsSettings(); GraphicsSetting = LoadSetting<GraphicsSettingModel>();
InteractiveSetting = LoadSetting<InteractiveSettingModel>();
SystemSetting = LoadSetting<SystemSettingModel>();
} }
private GraphicsSettingModel LoadGraphicsSettings() private T LoadSetting<T>()
where T : new()
{ {
var graphicsSetting = new GraphicsSettingModel(); var setting = new T();
ReflectionUtils.SetValue(_setting, graphicsSetting); ReflectionUtils.SetValue(_setting, setting);
return graphicsSetting; return setting;
} }
public void Save() public void Save()
{ {
SaveGraphicsSettings(); SaveSetting(GraphicsSetting);
SaveSetting(InteractiveSetting);
SaveSetting(SystemSetting);
File.WriteAllText(FilePath, _setting.ToString()); File.WriteAllText(FilePath, _setting.ToString());
} }
private void SaveGraphicsSettings() private void SaveSetting(object setting)
{ {
ReflectionUtils.SetValue(GraphicsSetting, _setting, _saveReflectionOptions); ReflectionUtils.SetValue(setting, _setting, _saveReflectionOptions);
} }
} }

View File

@ -1,4 +1,6 @@
namespace VPet.Solution.Models.SettingEditor; using System.Collections.ObjectModel;
namespace VPet.Solution.Models.SettingEditor;
public class SystemSettingModel : ObservableClass<SystemSettingModel> public class SystemSettingModel : ObservableClass<SystemSettingModel>
{ {
@ -7,47 +9,62 @@ public class SystemSettingModel : ObservableClass<SystemSettingModel>
/// </summary> /// </summary>
public bool DiagnosisDayEnable { get; } = true; public bool DiagnosisDayEnable { get; } = true;
#region Diagnosis
private bool _diagnosis; private bool _diagnosis;
/// <summary> /// <summary>
/// 是否启用数据收集 /// 是否启用数据收集
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.Diagnosis))]
public bool Diagnosis public bool Diagnosis
{ {
get => _diagnosis; get => _diagnosis;
set => SetProperty(ref _diagnosis, value); set => SetProperty(ref _diagnosis, value);
} }
#endregion
#region DiagnosisInterval
private int _diagnosisInterval; private int _diagnosisInterval;
/// <summary> /// <summary>
/// 数据收集频率 /// 数据收集频率
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.DiagnosisInterval))]
public int DiagnosisInterval public int DiagnosisInterval
{ {
get => _diagnosisInterval; get => _diagnosisInterval;
set => SetProperty(ref _diagnosisInterval, value); set => SetProperty(ref _diagnosisInterval, value);
} }
#endregion
#region AutoSaveInterval
private int _autoSaveInterval; private int _autoSaveInterval;
/// <summary> /// <summary>
/// 自动保存频率 (min) /// 自动保存频率 (min)
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.AutoSaveInterval))]
public int AutoSaveInterval public int AutoSaveInterval
{ {
get => _autoSaveInterval; get => _autoSaveInterval;
set => SetProperty(ref _autoSaveInterval, value); set => SetProperty(ref _autoSaveInterval, value);
} }
public static ObservableCollection<int> SaveIntervals { get; } =
new() { -1, 2, 5, 10, 20, 30, 60 };
#endregion
#region BackupSaveMaxNum
private int _backupSaveMaxNum; private int _backupSaveMaxNum;
/// <summary> /// <summary>
/// 备份保存最大数量 /// 备份保存最大数量
/// </summary> /// </summary>
[ReflectionProperty(nameof(VPet_Simulator.Windows.Interface.Setting.BackupSaveMaxNum))]
public int BackupSaveMaxNum public int BackupSaveMaxNum
{ {
get => _backupSaveMaxNum; get => _backupSaveMaxNum;
set => SetProperty(ref _backupSaveMaxNum, value); set => SetProperty(ref _backupSaveMaxNum, value);
} }
#endregion
} }

View File

@ -56,7 +56,7 @@
x:Key="TextBlock_BaseStyle" x:Key="TextBlock_BaseStyle"
BasedOn="{StaticResource {x:Type TextBlock}}" BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"> TargetType="TextBlock">
<Setter Property="Margin" Value="10,5,10,5" /> <Setter Property="Margin" Value="5" />
<Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" /> <Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" />
@ -139,7 +139,7 @@
</Style> </Style>
<Style x:Key="Switch_BaseStyle" TargetType="pu:Switch"> <Style x:Key="Switch_BaseStyle" TargetType="pu:Switch">
<Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Margin" Value="10,5,10,5" /> <Setter Property="Margin" Value="5" />
<Setter Property="Background" Value="{x:Null}" /> <Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryDark}" /> <Setter Property="BorderBrush" Value="{DynamicResource PrimaryDark}" />
<Setter Property="BoxHeight" Value="20" /> <Setter Property="BoxHeight" Value="20" />
@ -152,7 +152,7 @@
</Style> </Style>
<Style x:Key="Label_BaseStyle" TargetType="Label"> <Style x:Key="Label_BaseStyle" TargetType="Label">
<Setter Property="FontSize" Value="14" /> <Setter Property="FontSize" Value="14" />
<Setter Property="Margin" Value="10,0,10,0" /> <Setter Property="Margin" Value="10,5,10,5" />
<Setter Property="Height" Value="30" /> <Setter Property="Height" Value="30" />
<Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" />
@ -160,7 +160,7 @@
</Style> </Style>
<Style x:Key="NumberInput_BaseStyle" TargetType="pu:NumberInput"> <Style x:Key="NumberInput_BaseStyle" TargetType="pu:NumberInput">
<Setter Property="Height" Value="30" /> <Setter Property="Height" Value="30" />
<Setter Property="Margin" Value="10,5,10,5" /> <Setter Property="Margin" Value="5" />
<Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Background" Value="{x:Null}" /> <Setter Property="Background" Value="{x:Null}" />
<Setter Property="FontSize" Value="14" /> <Setter Property="FontSize" Value="14" />
@ -171,8 +171,8 @@
x:Key="Button_BaseStyle" x:Key="Button_BaseStyle"
BasedOn="{StaticResource {x:Type Button}}" BasedOn="{StaticResource {x:Type Button}}"
TargetType="Button"> TargetType="Button">
<Setter Property="Margin" Value="10,5,10,5" /> <Setter Property="Margin" Value="5" />
<Setter Property="Padding" Value="10,5,10,5" /> <Setter Property="Padding" Value="5" />
<Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="pu:ButtonHelper.CornerRadius" Value="4" /> <Setter Property="pu:ButtonHelper.CornerRadius" Value="4" />
@ -184,7 +184,7 @@
x:Key="ComboBox_BaseStyle" x:Key="ComboBox_BaseStyle"
BasedOn="{StaticResource StandardComboBoxStyle}" BasedOn="{StaticResource StandardComboBoxStyle}"
TargetType="ComboBox"> TargetType="ComboBox">
<Setter Property="Margin" Value="10,5,10,5" /> <Setter Property="Margin" Value="5" />
</Style> </Style>
<Style <Style
x:Key="Expander_BaseStyle" x:Key="Expander_BaseStyle"
@ -202,7 +202,7 @@
BasedOn="{StaticResource StandardSliderStyle}" BasedOn="{StaticResource StandardSliderStyle}"
TargetType="Slider"> TargetType="Slider">
<Setter Property="IsSnapToTickEnabled" Value="True" /> <Setter Property="IsSnapToTickEnabled" Value="True" />
<Setter Property="Margin" Value="10,5,10,5" /> <Setter Property="Margin" Value="5" />
<Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Center" />
</Style> </Style>
</ResourceDictionary> </ResourceDictionary>

View File

@ -11,8 +11,13 @@ namespace HKW.HKWUtils;
public static class ReflectionUtils public static class ReflectionUtils
{ {
private static readonly BindingFlags _propertyBindingFlags =
BindingFlags.Instance | BindingFlags.Public;
private static readonly Dictionary<Type, IReflectionConverter> _reflectionConverters = new();
/// <summary> /// <summary>
/// 目标名称 /// 类型信息
/// <para> /// <para>
/// (TargetType, (PropertyName, TargetPropertyName)) /// (TargetType, (PropertyName, TargetPropertyName))
/// </para> /// </para>
@ -20,15 +25,11 @@ public static class ReflectionUtils
private static readonly Dictionary<Type, ReflectionObjectInfo> _typePropertyReflectionInfos = private static readonly Dictionary<Type, ReflectionObjectInfo> _typePropertyReflectionInfos =
new(); new();
public static void SetValue<TSource, TTarget>( public static void SetValue(object source, object target, ReflectionOptions options = null!)
TSource source,
TTarget target,
ReflectionOptions options = null!
)
{ {
options ??= new(); options ??= new();
var sourceType = typeof(TSource); var sourceType = source.GetType();
var targetType = typeof(TTarget); var targetType = target.GetType();
if (_typePropertyReflectionInfos.TryGetValue(sourceType, out var sourceInfo) is false) if (_typePropertyReflectionInfos.TryGetValue(sourceType, out var sourceInfo) is false)
sourceInfo = _typePropertyReflectionInfos[sourceType] = GetReflectionObjectInfo( sourceInfo = _typePropertyReflectionInfos[sourceType] = GetReflectionObjectInfo(
sourceType sourceType
@ -41,24 +42,26 @@ public static class ReflectionUtils
var sourceAccessor = ObjectAccessor.Create(source); var sourceAccessor = ObjectAccessor.Create(source);
var targetAccessor = ObjectAccessor.Create(target); var targetAccessor = ObjectAccessor.Create(target);
foreach (var property in sourceType.GetProperties()) foreach (var property in targetType.GetProperties(_propertyBindingFlags))
{ {
// 获取源属性名 // 尝试获取目标属性信息
var sourcePropertyName = sourceInfo.PropertyInfos.TryGetValue( targetInfo.PropertyInfos.TryGetValue(property.Name, out var targetReflectionInfo);
property.Name, // 检测忽视
out var sourceReflectionInfo if (targetReflectionInfo?.IsIgnore is true)
)
? sourceReflectionInfo.PropertyName
: property.Name;
if (targetInfo.PropertyNames.Contains(sourcePropertyName) is false)
continue; continue;
// 获取目标属性名 // 获取源属性名
var targetPropertyName = targetInfo.PropertyInfos.TryGetValue( var sourcePropertyName = targetReflectionInfo is null
sourcePropertyName, ? property.Name
out var targetReflectionInfo : targetReflectionInfo.TargetName;
) // 获取源属性信息
? targetReflectionInfo.PropertyName sourceInfo.PropertyInfos.TryGetValue(sourcePropertyName, out var sourceReflectionInfo);
: property.Name; if (sourceInfo.PropertyNames.Contains(sourcePropertyName) is false)
{
if (targetReflectionInfo?.IsRequired is true)
options.UnassignedRequiredProperties.Add(property.Name);
continue;
}
// 获取源值 // 获取源值
var sourceValue = sourceAccessor[sourcePropertyName]; var sourceValue = sourceAccessor[sourcePropertyName];
// 转换源值 // 转换源值
@ -69,26 +72,62 @@ public static class ReflectionUtils
// 比较源值和目标值 // 比较源值和目标值
if (options.CheckValueEquals) if (options.CheckValueEquals)
{ {
var targetValue = targetAccessor[targetPropertyName]; var targetValue = targetAccessor[property.Name];
if (sourceValue.Equals(targetValue)) if (sourceValue.Equals(targetValue))
continue; continue;
} }
targetAccessor[targetPropertyName] = sourceValue; targetAccessor[property.Name] = sourceValue;
} }
} }
private static ReflectionObjectInfo GetReflectionObjectInfo(Type type) private static ReflectionObjectInfo GetReflectionObjectInfo(Type type)
{ {
var objectInfo = new ReflectionObjectInfo(type); var objectInfo = new ReflectionObjectInfo(type);
foreach (var property in type.GetProperties()) foreach (var property in type.GetProperties(_propertyBindingFlags))
{ {
if (property.IsDefined(typeof(ReflectionPropertyInfoAttribute))) // 获取是否被忽视
if (property.IsDefined(typeof(ReflectionPropertyIgnoreAttribute)))
{ {
var reflectionInfo = property.GetCustomAttribute<ReflectionPropertyInfoAttribute>(); objectInfo.PropertyInfos[property.Name] = new(property.Name) { IsIgnore = true };
if (string.IsNullOrWhiteSpace(reflectionInfo.PropertyName)) continue;
reflectionInfo.PropertyName = property.Name;
objectInfo.PropertyInfos[property.Name] = reflectionInfo;
} }
if (
property.IsDefined(typeof(ReflectionPropertyAttribute)) is false
&& property.IsDefined(typeof(ReflectionPropertyConverterAttribute)) is false
)
continue;
var propertyInfo = new ReflectionPropertyInfo(property.Name);
// 获取属性信息
if (
property.GetCustomAttribute<ReflectionPropertyAttribute>()
is ReflectionPropertyAttribute propertyInfoAttribute
)
{
if (string.IsNullOrWhiteSpace(propertyInfoAttribute.TargetPropertyName) is false)
propertyInfo.TargetName = propertyInfoAttribute.TargetPropertyName;
propertyInfo.IsRequired = propertyInfoAttribute.IsRequired;
}
// 获取属性转换器
if (
property.GetCustomAttribute<ReflectionPropertyConverterAttribute>()
is ReflectionPropertyConverterAttribute propertyConverterAttribute
)
{
if (
_reflectionConverters.TryGetValue(
propertyConverterAttribute.ConverterType,
out var converter
)
is false
)
converter = _reflectionConverters[propertyConverterAttribute.ConverterType] =
(IReflectionConverter)
TypeAccessor
.Create(propertyConverterAttribute.ConverterType)
.CreateNew();
propertyInfo.Converter = converter;
}
objectInfo.PropertyInfos[property.Name] = propertyInfo;
} }
return objectInfo; return objectInfo;
} }
@ -101,41 +140,97 @@ public class ReflectionObjectInfo
{ {
public HashSet<string> PropertyNames { get; } public HashSet<string> PropertyNames { get; }
public Dictionary<string, ReflectionPropertyInfoAttribute> PropertyInfos { get; } = new(); public Dictionary<string, ReflectionPropertyInfo> PropertyInfos { get; } = new();
public ReflectionObjectInfo(Type type) public ReflectionObjectInfo(Type type)
{ {
PropertyNames = new(type.GetProperties().Select(p => p.Name)); PropertyNames = new(
type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => p.Name)
);
}
}
public class ReflectionPropertyInfo
{
/// <summary>
/// 目标属性名称
/// </summary>
public string TargetName { get; set; }
/// <summary>
/// 是必要的
/// </summary>
[DefaultValue(false)]
public bool IsRequired { get; set; } = false;
/// <summary>
/// 是忽视的
/// </summary>
public bool IsIgnore { get; set; } = false;
/// <summary>
/// 反射值转换器
/// </summary>
public IReflectionConverter? Converter { get; set; } = null;
public ReflectionPropertyInfo(string propertyName)
{
TargetName = propertyName;
} }
} }
/// <summary> /// <summary>
/// 反射属性信息 /// 反射属性信息
/// </summary> /// </summary>
public class ReflectionPropertyInfoAttribute : Attribute [AttributeUsage(AttributeTargets.Property)]
public class ReflectionPropertyAttribute : Attribute
{ {
/// <summary> /// <summary>
/// 目标属性名称 /// 属性名称
/// </summary> /// </summary>
public string PropertyName { get; set; } public string TargetPropertyName { get; }
/// <summary>
/// 是必要的
/// </summary>
[DefaultValue(true)]
public bool IsRequired { get; } = true;
public ReflectionPropertyAttribute(bool isRequired = true)
{
IsRequired = isRequired;
}
public ReflectionPropertyAttribute(string targetPropertyName, bool isRequired = true)
{
TargetPropertyName = targetPropertyName;
IsRequired = isRequired;
}
}
/// <summary>
/// 反射属性转换器
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ReflectionPropertyConverterAttribute : Attribute
{
/// <summary> /// <summary>
/// 反射转换器 /// 反射转换器
/// </summary> /// </summary>
public IReflectionConverter? Converter { get; } = null; public Type ConverterType { get; }
public ReflectionPropertyInfoAttribute(Type converterType) public ReflectionPropertyConverterAttribute(Type converterType)
: this(string.Empty, converterType) { }
public ReflectionPropertyInfoAttribute(string name, Type? converterType = null)
{ {
PropertyName = name; ConverterType = converterType;
if (converterType is null)
return;
Converter = (IReflectionConverter)TypeAccessor.Create(converterType).CreateNew();
} }
} }
/// <summary>
/// 反射属性忽视
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ReflectionPropertyIgnoreAttribute : Attribute { }
/// <summary> /// <summary>
/// 反射设置 /// 反射设置
/// </summary> /// </summary>
@ -146,6 +241,11 @@ public class ReflectionOptions
/// </summary> /// </summary>
[DefaultValue(false)] [DefaultValue(false)]
public bool CheckValueEquals { get; set; } = false; public bool CheckValueEquals { get; set; } = false;
/// <summary>
/// 未赋值的必要属性
/// </summary>
public List<string> UnassignedRequiredProperties { get; set; } = new();
} }
/// <summary> /// <summary>

View File

@ -77,6 +77,13 @@ public static class Utils
return bitmapImage; return bitmapImage;
} }
/// <summary>
/// 获取布尔值
/// </summary>
/// <param name="value">值</param>
/// <param name="boolValue">目标布尔值</param>
/// <param name="nullValue">为空时布尔值</param>
/// <returns></returns>
public static bool GetBool(object value, bool boolValue, bool nullValue) public static bool GetBool(object value, bool boolValue, bool nullValue)
{ {
if (value is null) if (value is null)
@ -88,4 +95,26 @@ public static class Utils
else else
return false; return false;
} }
/// <summary>
/// 打开文件
/// </summary>
/// <param name="filePath">文件路径</param>
public static void OpenFile(string filePath)
{
System.Diagnostics.Process
.Start(new System.Diagnostics.ProcessStartInfo(filePath) { UseShellExecute = true })
?.Close();
}
/// <summary>
/// 从资源管理器打开文件
/// </summary>
/// <param name="filePath">文件路径</param>
public static void OpenFileInExplorer(string filePath)
{
System.Diagnostics.Process
.Start("Explorer", $"/select,{Path.GetFullPath(filePath)}")
?.Close();
}
} }

View File

@ -95,6 +95,8 @@
<Compile Include="Converters\MaxConverter.cs" /> <Compile Include="Converters\MaxConverter.cs" />
<Compile Include="Converters\ValueToBoolConverter.cs" /> <Compile Include="Converters\ValueToBoolConverter.cs" />
<Compile Include="Converters\BoolInverter.cs" /> <Compile Include="Converters\BoolInverter.cs" />
<Compile Include="Models\SaveViewer\SaveModel.cs" />
<Compile Include="Models\SaveViewer\StatisticDataModel.cs" />
<Compile Include="Models\SettingEditor\GraphicsSettingModel.cs" /> <Compile Include="Models\SettingEditor\GraphicsSettingModel.cs" />
<Compile Include="Models\SettingEditor\InteractiveSettingModel.cs" /> <Compile Include="Models\SettingEditor\InteractiveSettingModel.cs" />
<Compile Include="Models\SettingEditor\SystemSettingModel.cs" /> <Compile Include="Models\SettingEditor\SystemSettingModel.cs" />
@ -103,11 +105,23 @@
<Compile Include="Utils\FindTopParent.cs" /> <Compile Include="Utils\FindTopParent.cs" />
<Compile Include="Utils\ReflectionUtils.cs" /> <Compile Include="Utils\ReflectionUtils.cs" />
<Compile Include="ViewModels\MainWindowVM.cs" /> <Compile Include="ViewModels\MainWindowVM.cs" />
<Compile Include="ViewModels\SaveViewer\SaveDataPageVM.cs" />
<Compile Include="ViewModels\SaveViewer\SaveStatisticPageVM.cs" />
<Compile Include="ViewModels\SaveViewer\SaveWindowVM.cs" />
<Compile Include="ViewModels\SettingEditor\CustomizedSettingPageVM.cs" /> <Compile Include="ViewModels\SettingEditor\CustomizedSettingPageVM.cs" />
<Compile Include="ViewModels\SettingEditor\DiagnosticSettingPageVM.cs" /> <Compile Include="ViewModels\SettingEditor\DiagnosticSettingPageVM.cs" />
<Compile Include="ViewModels\SettingEditor\ModSettingPageVM.cs" /> <Compile Include="ViewModels\SettingEditor\ModSettingPageVM.cs" />
<Compile Include="Models\SettingEditor\SettingModel.cs" /> <Compile Include="Models\SettingEditor\SettingModel.cs" />
<Compile Include="ViewModels\SettingEditor\SystemSettingPageVM.cs" /> <Compile Include="ViewModels\SettingEditor\SystemSettingPageVM.cs" />
<Compile Include="Views\SaveViewer\SaveDataPage.xaml.cs">
<DependentUpon>SaveDataPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SaveViewer\SaveStatisticPage.xaml.cs">
<DependentUpon>SaveStatisticPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SaveViewer\SaveWindow.xaml.cs">
<DependentUpon>SaveWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingEditor\SettingWindow.xaml.cs"> <Compile Include="Views\SettingEditor\SettingWindow.xaml.cs">
<DependentUpon>SettingWindow.xaml</DependentUpon> <DependentUpon>SettingWindow.xaml</DependentUpon>
</Compile> </Compile>
@ -135,6 +149,18 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Views\SaveViewer\SaveDataPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SaveViewer\SaveStatisticPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SaveViewer\SaveWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\SettingEditor\SettingWindow.xaml"> <Page Include="Views\SettingEditor\SettingWindow.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
@ -250,10 +276,6 @@
<Name>VPet-Simulator.Windows.Interface</Name> <Name>VPet-Simulator.Windows.Interface</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup />
<Folder Include="Models\SaveEditor\" />
<Folder Include="ViewModels\SaveEditor\" />
<Folder Include="Views\SaveEditor\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VPet.Solution.Models.SaveViewer;
using VPet.Solution.Views.SaveViewer;
namespace VPet.Solution.ViewModels.SaveViewer;
public class SaveDataPageVM : ObservableClass<SaveDataPageVM>
{
private SaveModel _save;
public SaveModel Save
{
get => _save;
set => SetProperty(ref _save, value);
}
public SaveDataPageVM()
{
SaveWindowVM.Current.PropertyChangedX += Current_PropertyChangedX;
}
private void Current_PropertyChangedX(SaveWindowVM sender, PropertyChangedXEventArgs e)
{
if (e.PropertyName == nameof(SaveWindowVM.CurrentSave) && sender.CurrentSave is not null)
{
Save = sender.CurrentSave;
}
}
}

View File

@ -0,0 +1,71 @@
using HKW.HKWUtils.Observable;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VPet.Solution.Models.SaveViewer;
namespace VPet.Solution.ViewModels.SaveViewer;
public class SaveStatisticPageVM : ObservableClass<SaveStatisticPageVM>
{
#region Properties
#region Save
private SaveModel _save;
public SaveModel Save
{
get => _save;
set => SetProperty(ref _save, value);
}
#endregion
#region ShowStatistics
private IEnumerable<StatisticDataModel> _showStatistics;
public IEnumerable<StatisticDataModel> ShowStatistics
{
get => _showStatistics;
set => SetProperty(ref _showStatistics, value);
}
#endregion
#region SearchStatistic
private string _searchStatistic;
public string SearchStatistic
{
get => _searchStatistic;
set
{
SetProperty(ref _searchStatistic, value);
RefreshShowStatistics(value);
}
}
#endregion
#endregion
public SaveStatisticPageVM()
{
SaveWindowVM.Current.PropertyChangedX += Current_PropertyChangedX;
}
private void Current_PropertyChangedX(SaveWindowVM sender, PropertyChangedXEventArgs e)
{
if (e.PropertyName == nameof(SaveWindowVM.CurrentSave) && sender.CurrentSave is not null)
{
Save = sender.CurrentSave;
ShowStatistics = Save.Statistics;
}
}
public void RefreshShowStatistics(string name)
{
if (string.IsNullOrWhiteSpace(name))
ShowStatistics = Save.Statistics;
else
ShowStatistics = Save.Statistics.Where(
s => s.Name.Contains(SearchStatistic, StringComparison.OrdinalIgnoreCase)
);
}
}

View File

@ -0,0 +1,114 @@
using HKW.HKWUtils.Observable;
using LinePutScript;
using LinePutScript.Localization.WPF;
using Panuon.WPF.UI;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using VPet.Solution.Models;
using VPet.Solution.Models.SaveViewer;
using VPet.Solution.Models.SettingEditor;
using VPet.Solution.Views.SettingEditor;
using VPet_Simulator.Windows.Interface;
namespace VPet.Solution.ViewModels.SaveViewer;
public class SaveWindowVM : ObservableClass<SaveWindowVM>
{
public static SaveWindowVM Current { get; private set; }
#region Properties
private SaveModel _currentSave;
public SaveModel CurrentSave
{
get => _currentSave;
set => SetProperty(ref _currentSave, value);
}
private readonly ObservableCollection<SaveModel> _saves = new();
private IEnumerable<SaveModel> _showSaves;
public IEnumerable<SaveModel> ShowSaves
{
get => _showSaves;
set => SetProperty(ref _showSaves, value);
}
private string _searchSave;
public string SearchSave
{
get => _searchSave;
set => SetProperty(ref _searchSave, value);
}
#endregion
#region Command
/// <summary>
/// 打开文件
/// </summary>
public ObservableCommand<SaveModel> OpenFileCommand { get; } = new();
/// <summary>
/// 从资源管理器打开
/// </summary>
public ObservableCommand<SaveModel> OpenFileInExplorerCommand { get; } = new();
#endregion
public SaveWindowVM()
{
Current = this;
ShowSaves = _saves;
LoadSaves();
PropertyChanged += SaveWindowVM_PropertyChanged;
OpenFileCommand.ExecuteCommand += OpenFileCommand_ExecuteCommand;
OpenFileInExplorerCommand.ExecuteCommand += OpenFileInExplorerCommand_ExecuteCommand;
}
private void OpenFileInExplorerCommand_ExecuteCommand(SaveModel parameter)
{
Utils.OpenFileInExplorer(parameter.FilePath);
}
private void OpenFileCommand_ExecuteCommand(SaveModel parameter)
{
Utils.OpenFile(parameter.FilePath);
}
public void RefreshShowSaves(string name)
{
if (string.IsNullOrWhiteSpace(name))
ShowSaves = _saves;
else
ShowSaves = _saves.Where(
s => s.Name.Contains(SearchSave, StringComparison.OrdinalIgnoreCase)
);
}
private void SaveWindowVM_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SearchSave))
{
RefreshShowSaves(SearchSave);
}
}
private void LoadSaves()
{
var saveDirectory = Path.Combine(Environment.CurrentDirectory, "Saves");
if (Directory.Exists(saveDirectory) is false)
return;
foreach (var file in Directory.EnumerateFiles(saveDirectory).Where(s => s.EndsWith(".lps")))
{
var lps = new LPS(File.ReadAllText(file));
var save = new GameSave_v2(lps);
var saveModel = new SaveModel(file, save);
_saves.Add(saveModel);
}
}
}

View File

@ -24,7 +24,10 @@ public class InteractiveSettingPageVM : ObservableClass<InteractiveSettingPageVM
private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e) private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e)
{ {
if (e.PropertyName == nameof(SettingWindowVM.CurrentSetting)) if (
e.PropertyName == nameof(SettingWindowVM.CurrentSetting)
&& sender.CurrentSetting is not null
)
{ {
InteractiveSetting = sender.CurrentSetting.InteractiveSetting; InteractiveSetting = sender.CurrentSetting.InteractiveSetting;
} }

View File

@ -48,26 +48,68 @@ public class SettingWindowVM : ObservableClass<SettingWindowVM>
#endregion #endregion
#region Command #region Command
/// <summary>
/// 打开文件
/// </summary>
public ObservableCommand<SettingModel> OpenFileCommand { get; } = new();
/// <summary>
/// 从资源管理器打开
/// </summary>
public ObservableCommand<SettingModel> OpenFileInExplorerCommand { get; } = new();
/// <summary>
/// 重置
/// </summary>
public ObservableCommand<SettingModel> ResetSettingCommand { get; } = new(); public ObservableCommand<SettingModel> ResetSettingCommand { get; } = new();
/// <summary>
/// 保存
/// </summary>
public ObservableCommand<SettingModel> SaveSettingCommand { get; } = new(); public ObservableCommand<SettingModel> SaveSettingCommand { get; } = new();
/// <summary>
/// 保存全部
/// </summary>
public ObservableCommand SaveAllSettingCommand { get; } = new(); public ObservableCommand SaveAllSettingCommand { get; } = new();
#endregion #endregion
public SettingWindowVM() public SettingWindowVM()
{ {
Current = this; Current = this;
ShowSettings = _settings; ShowSettings = _settings;
LoadSettings();
foreach (var s in LoadSettings())
_settings.Add(s);
PropertyChanged += MainWindowVM_PropertyChanged; PropertyChanged += MainWindowVM_PropertyChanged;
OpenFileCommand.ExecuteCommand += OpenFileCommand_ExecuteCommand;
OpenFileInExplorerCommand.ExecuteCommand += OpenFileInExplorerCommand_ExecuteCommand;
ResetSettingCommand.ExecuteCommand += ResetSettingCommand_ExecuteCommand; ResetSettingCommand.ExecuteCommand += ResetSettingCommand_ExecuteCommand;
SaveSettingCommand.ExecuteCommand += SaveSettingCommand_ExecuteCommand; SaveSettingCommand.ExecuteCommand += SaveSettingCommand_ExecuteCommand;
SaveAllSettingCommand.ExecuteCommand += SaveAllSettingCommand_ExecuteCommand; SaveAllSettingCommand.ExecuteCommand += SaveAllSettingCommand_ExecuteCommand;
} }
private void OpenFileInExplorerCommand_ExecuteCommand(SettingModel parameter)
{
Utils.OpenFileInExplorer(parameter.FilePath);
}
private void OpenFileCommand_ExecuteCommand(SettingModel parameter)
{
Utils.OpenFile(parameter.FilePath);
}
private void SaveAllSettingCommand_ExecuteCommand() private void SaveAllSettingCommand_ExecuteCommand()
{ {
if (
MessageBox.Show(
SettingWindow.Instance,
"确定全部保存吗".Translate(),
"",
MessageBoxButton.YesNo,
MessageBoxImage.Warning
)
is not MessageBoxResult.Yes
)
return;
foreach (var setting in _settings) foreach (var setting in _settings)
setting.Save(); setting.Save();
} }
@ -90,9 +132,7 @@ public class SettingWindowVM : ObservableClass<SettingWindowVM>
is not MessageBoxResult.Yes is not MessageBoxResult.Yes
) )
return; return;
CurrentSetting = _settings[_settings.IndexOf(CurrentSetting)] = new SettingModel( CurrentSetting = _settings[_settings.IndexOf(CurrentSetting)] = new SettingModel()
new Setting("")
)
{ {
Name = CurrentSetting.Name, Name = CurrentSetting.Name,
FilePath = CurrentSetting.FilePath FilePath = CurrentSetting.FilePath
@ -118,10 +158,39 @@ public class SettingWindowVM : ObservableClass<SettingWindowVM>
} }
} }
public static IEnumerable<SettingModel> LoadSettings() private void LoadSettings()
{ {
foreach ( foreach (var file in GetSettingFiles())
var file in Directory {
var fileName = Path.GetFileNameWithoutExtension(file);
try
{
var setting = new Setting(File.ReadAllText(file));
var settingModel = new SettingModel(setting) { Name = fileName, FilePath = file };
_settings.Add(settingModel);
}
catch (Exception ex)
{
if (
MessageBox.Show(
"设置载入失败, 是否强制载入并重置\n[是]: 载入并重置\t[否]: 取消载入\n名称: {0}\n路径: {1}\n异常: {2}".Translate(
fileName,
file,
ex.ToString()
),
"载入设置出错".Translate(),
MessageBoxButton.YesNo,
MessageBoxImage.Warning
) is MessageBoxResult.Yes
)
_settings.Add(new SettingModel() { Name = fileName, FilePath = file });
}
}
}
private static IEnumerable<string> GetSettingFiles()
{
return Directory
.EnumerateFiles(Environment.CurrentDirectory) .EnumerateFiles(Environment.CurrentDirectory)
.Where( .Where(
(s) => (s) =>
@ -130,15 +199,6 @@ public class SettingWindowVM : ObservableClass<SettingWindowVM>
return false; return false;
return Path.GetFileName(s).StartsWith("Setting"); return Path.GetFileName(s).StartsWith("Setting");
} }
) );
)
{
var setting = new Setting(File.ReadAllText(file));
yield return new SettingModel(setting)
{
Name = Path.GetFileNameWithoutExtension(file),
FilePath = file
};
}
} }
} }

View File

@ -11,12 +11,15 @@ namespace VPet.Solution.ViewModels.SettingEditor;
public class SystemSettingPageVM : ObservableClass<SystemSettingPageVM> public class SystemSettingPageVM : ObservableClass<SystemSettingPageVM>
{ {
#region SystemSetting
private SystemSettingModel _systemSetting; private SystemSettingModel _systemSetting;
public SystemSettingModel SystemSetting public SystemSettingModel SystemSetting
{ {
get => _systemSetting; get => _systemSetting;
set => SetProperty(ref _systemSetting, value); set => SetProperty(ref _systemSetting, value);
} }
#endregion
public SystemSettingPageVM() public SystemSettingPageVM()
{ {
@ -25,7 +28,10 @@ public class SystemSettingPageVM : ObservableClass<SystemSettingPageVM>
private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e) private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e)
{ {
if (e.PropertyName == nameof(SettingWindowVM.CurrentSetting)) if (
e.PropertyName == nameof(SettingWindowVM.CurrentSetting)
&& sender.CurrentSetting is not null
)
{ {
SystemSetting = sender.CurrentSetting.SystemSetting; SystemSetting = sender.CurrentSetting.SystemSetting;
} }

View File

@ -31,7 +31,8 @@
<Button <Button
x:Name="Button_OpenSaveEditor" x:Name="Button_OpenSaveEditor"
Grid.Column="1" Grid.Column="1"
Content="{ll:Str 打开存档编辑器}" Click="Button_OpenSaveEditor_Click"
Content="{ll:Str 打开存档查看器}"
FontSize="16" FontSize="16"
Style="{DynamicResource Button_BaseStyle}" /> Style="{DynamicResource Button_BaseStyle}" />
</Grid> </Grid>

View File

@ -4,6 +4,7 @@ using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using VPet.Solution.ViewModels; using VPet.Solution.ViewModels;
using VPet.Solution.Views.SaveViewer;
using VPet.Solution.Views.SettingEditor; using VPet.Solution.Views.SettingEditor;
namespace VPet.Solution.Views; namespace VPet.Solution.Views;
@ -15,7 +16,8 @@ public partial class MainWindow : WindowX
{ {
public MainWindowVM ViewModel => (MainWindowVM)DataContext; public MainWindowVM ViewModel => (MainWindowVM)DataContext;
public SettingWindow SettingWindow { get; set; } = new(); public SettingWindow SettingWindow { get; } = new();
public SaveWindow SaveWindow { get; } = new();
public MainWindow() public MainWindow()
{ {
@ -33,10 +35,16 @@ public partial class MainWindow : WindowX
private void MainWindow_Closed(object sender, EventArgs e) private void MainWindow_Closed(object sender, EventArgs e)
{ {
SettingWindow.CloseX(); SettingWindow.CloseX();
SaveWindow.CloseX();
} }
private void Button_OpenSettingEditor_Click(object sender, RoutedEventArgs e) private void Button_OpenSettingEditor_Click(object sender, RoutedEventArgs e)
{ {
SettingWindow.ShowOrActivate(); SettingWindow.ShowOrActivate();
} }
private void Button_OpenSaveEditor_Click(object sender, RoutedEventArgs e)
{
SaveWindow.ShowOrActivate();
}
} }

View File

@ -0,0 +1,99 @@
<Page
x:Class="VPet.Solution.Views.SaveViewer.SaveDataPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:h="clr-namespace:HKW.WPF.Helpers"
xmlns:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF"
xmlns:local="clr-namespace:VPet.Solution.Views.SaveViewer"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pu="https://opensource.panuon.com/wpf-ui"
xmlns:vm="clr-namespace:VPet.Solution.ViewModels.SaveViewer"
Title="SaveDataPage"
d:DataContext="{d:DesignInstance Type=vm:SaveDataPageVM}"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<StackPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 保存日期}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.DateSaved, StringFormat='yyyy/MM/dd HH:mm:ss'}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 宠物名称}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.PetName}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 模式}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.Mode}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 等级}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.Exp}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 金钱}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.Money}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 经验}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.Level}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 体力}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.Strength}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 心情}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.Feeling}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 饱腹度}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.StrengthFood}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 口渴度}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.StrengthDrink}" />
</DockPanel>
<DockPanel>
<Label
h:ElementHelper.UniformMinWidthGroup="A"
Content="{ll:Str 哈希检查}"
Style="{DynamicResource Label_BaseStyle}" />
<TextBlock Style="{DynamicResource TextBlock_LeftCenter}" Text="{Binding Save.HashChecked}" />
</DockPanel>
</StackPanel>
</ScrollViewer>
</Page>

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
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;
using VPet.Solution.ViewModels.SaveViewer;
namespace VPet.Solution.Views.SaveViewer;
/// <summary>
/// SaveDataPage.xaml 的交互逻辑
/// </summary>
public partial class SaveDataPage : Page
{
public SaveDataPageVM ViewModel => (SaveDataPageVM)DataContext;
public SaveDataPage()
{
InitializeComponent();
this.SetViewModel<SaveDataPageVM>();
}
}

View File

@ -0,0 +1,56 @@
<Page
x:Class="VPet.Solution.Views.SaveViewer.SaveStatisticPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF"
xmlns:local="clr-namespace:VPet.Solution.Views.SaveViewer"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pu="https://opensource.panuon.com/wpf-ui"
xmlns:vm="clr-namespace:VPet.Solution.ViewModels.SaveViewer"
Title="SaveStatisticPage"
d:DataContext="{d:DesignInstance Type=vm:SaveStatisticPageVM}"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox
x:Name="TextBox_Search"
pu:TextBoxHelper.Watermark="{ll:Str 搜索统计}"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding SearchStatistic, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid
x:Name="DataGridStatic"
Grid.Row="1"
Margin="0,5,0,0"
d:ItemsSource="{d:SampleData ItemCount=5}"
AutoGenerateColumns="False"
CanUserAddRows="False"
ItemsSource="{Binding ShowStatistics}">
<DataGrid.RowStyle>
<Style BasedOn="{StaticResource {x:Type DataGridRow}}" TargetType="DataGridRow">
<Setter Property="ToolTip" Value="{Binding Id}" />
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn
Width="300"
Binding="{Binding Name}"
ElementStyle="{StaticResource TextBlock_LeftCenter}"
Header="{ll:Str 名称}"
IsReadOnly="True" />
<DataGridTextColumn
Width="200"
Binding="{Binding Value}"
ElementStyle="{StaticResource TextBlock_LeftCenter}"
Header="{ll:Str 值}"
IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Page>

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
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;
using VPet.Solution.ViewModels.SaveViewer;
namespace VPet.Solution.Views.SaveViewer;
/// <summary>
/// SaveStatisticPage.xaml 的交互逻辑
/// </summary>
public partial class SaveStatisticPage : Page
{
public SaveStatisticPageVM ViewModel => (SaveStatisticPageVM)DataContext;
public SaveStatisticPage()
{
InitializeComponent();
this.SetViewModel<SaveStatisticPageVM>();
}
}

View File

@ -0,0 +1,170 @@
<pu:WindowX
x:Class="VPet.Solution.Views.SaveViewer.SaveWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF"
xmlns:local="clr-namespace:VPet.Solution"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pu="https://opensource.panuon.com/wpf-ui"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:vm="clr-namespace:VPet.Solution.ViewModels.SaveViewer"
Title="{ll:Str 'VPET 存档查看器'}"
Width="800"
Height="450"
MinWidth="400"
MinHeight="200"
d:DataContext="{d:DesignInstance Type=vm:SaveWindowVM}"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="100" />
<ColumnDefinition MinWidth="300" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox
pu:TextBoxHelper.Watermark="{ll:Str 搜索存档}"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding SearchSave, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid
x:Name="DataGrid_Saves"
Grid.Row="1"
d:ItemsSource="{d:SampleData ItemCount=5}"
AutoGenerateColumns="False"
CanUserAddRows="False"
ItemsSource="{Binding ShowSaves}"
SelectedItem="{Binding CurrentSave}">
<DataGrid.RowStyle>
<Style BasedOn="{StaticResource {x:Type DataGridRow}}" TargetType="DataGridRow">
<Setter Property="Tag" Value="{Binding DataContext, RelativeSource={RelativeSource AncestorType=Window}}" />
<Setter Property="ToolTip" Value="{Binding FilePath}" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Mode=Self}}">
<MenuItem
Command="{Binding PlacementTarget.Tag.OpenFileCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}"
Header="{ll:Str 打开文件}" />
<MenuItem
Command="{Binding PlacementTarget.Tag.OpenFileInExplorerCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}"
Header="{ll:Str 从资源管理器打开文件}" />
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Name}"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 名称}"
IsReadOnly="True" />
<DataGridTextColumn
Binding="{Binding DateSaved, StringFormat='yyyy/MM/dd HH:mm:ss'}"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 保存时间}"
IsReadOnly="True" />
<DataGridTextColumn
Binding="{Binding TotalTime}"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 游玩时长}"
IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
</Grid>
<Grid Grid.Column="1" IsEnabled="{Binding SelectedItem, ElementName=DataGrid_Saves, Converter={StaticResource NullToFalse}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<ListBox x:Name="ListBox_Pages" Style="{DynamicResource SideMenuListBoxStyle}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem x:Name="ListBoxItem_SaveData" Content="{ll:Str 数据}" />
<ListBoxItem x:Name="ListBoxItem_SaveStatistic" Content="{ll:Str 统计}" />
</ListBox>
<Frame
x:Name="Frame_Main"
Grid.Row="1"
Content="{Binding SelectedItem.Tag, ElementName=ListBox_Pages}"
ContentRendered="Frame_Main_ContentRendered"
NavigationUIVisibility="Hidden" />
<!--<TabControl
x:Name="MainTab"
Grid.Column="1"
Margin="5"
d:SelectionChanged="MainTab_SelectionChanged"
pu:TabControlHelper.CanHeaderPanelScroll="True"
pu:TabControlHelper.ItemsCornerRadius="4"
pu:TabControlHelper.ItemsHeight="NaN"
pu:TabControlHelper.ItemsHoverBackground="{DynamicResource PrimaryLight}"
pu:TabControlHelper.ItemsPadding="10,7"
pu:TabControlHelper.ItemsSelectedBackground="{DynamicResource PrimaryDark}"
pu:TabControlHelper.ItemsSelectedForeground="{DynamicResource DARKPrimaryText}"
Background="Transparent"
BorderThickness="0"
Foreground="{DynamicResource PrimaryText}">
<TabControl.ContentTemplate>
<DataTemplate>
<Border
Margin="0,5,0,10"
Background="{DynamicResource DARKPrimaryText}"
CornerRadius="15">
<ContentControl Margin="10,5" Content="{Binding}" />
</Border>
</DataTemplate>
</TabControl.ContentTemplate>
<TabItem
BorderBrush="{DynamicResource PrimaryDarker}"
Foreground="{DynamicResource PrimaryText}"
Header="" />
<TabItem BorderBrush="{DynamicResource PrimaryDarker}" Header="{ll:Str 系统}" />
<TabItem BorderBrush="{DynamicResource PrimaryDarker}" Header="{ll:Str 互动}" />
<TabItem BorderBrush="{DynamicResource PrimaryDarker}" Header="{ll:Str 自定}" />
<TabItem BorderBrush="{DynamicResource PrimaryDarker}" Header="{ll:Str 诊断}" />
<TabItem BorderBrush="{DynamicResource PrimaryDarker}" Header="{ll:Str MOD管理}" />
</TabControl>
<Label
x:Name="GameVerison"
Grid.ColumnSpan="2"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Background="{x:Null}"
Content="版本v1.0 (655366666)"
FontSize="10"
Foreground="Green" />-->
</Grid>
<!--<Grid Grid.Column="1">
<TextBox
x:Name="tb_seach_menu"
Margin="3,6,6,0"
VerticalAlignment="Top"
d:TextChanged="tb_seach_menu_textchange"
pu:TextBoxHelper.Watermark="{ll:Str 搜索设置}"
FontSize="16"
Style="{DynamicResource StandardTextBoxStyle}" />
<ListBox
x:Name="ListMenu"
Margin="3,40,6,3"
pu:ListBoxHelper.CornerRadius="5"
pu:ListBoxHelper.ItemsHoverBackground="{DynamicResource Primary}"
pu:ListBoxHelper.ItemsSelectedBackground="{DynamicResource SecondaryLight}"
Background="{DynamicResource SecondaryLighter}"
BorderBrush="{DynamicResource Primary}"
BorderThickness="2"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto" />
</Grid>-->
</Grid>
</pu:WindowX>

View File

@ -0,0 +1,40 @@
using HKW.HKWUtils;
using Panuon.WPF.UI;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using VPet.Solution.ViewModels.SaveViewer;
using VPet.Solution.ViewModels.SettingEditor;
namespace VPet.Solution.Views.SaveViewer;
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class SaveWindow : WindowX
{
public static SaveWindow Instance { get; private set; }
public SaveWindowVM ViewModel => (SaveWindowVM)DataContext;
public SaveWindow()
{
InitializeComponent();
this.SetViewModel<SaveWindowVM>();
this.SetCloseState(WindowCloseState.Hidden);
ListBoxItem_SaveData.Tag = new SaveDataPage();
ListBoxItem_SaveStatistic.Tag = new SaveStatisticPage();
ListBox_Pages.SelectedIndex = 0;
Instance = this;
}
private void Frame_Main_ContentRendered(object sender, EventArgs e)
{
if (sender is not Frame frame)
return;
// 清理过时页面
while (frame.CanGoBack)
frame.RemoveBackEntry();
GC.Collect();
}
}

View File

@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using VPet.Solution.ViewModels.SettingEditor;
namespace VPet.Solution.Views.SettingEditor; namespace VPet.Solution.Views.SettingEditor;
@ -20,8 +21,11 @@ namespace VPet.Solution.Views.SettingEditor;
/// </summary> /// </summary>
public partial class CustomizedSettingPage : Page public partial class CustomizedSettingPage : Page
{ {
public CustomizedSettingPageVM ViewModel => (CustomizedSettingPageVM)DataContext;
public CustomizedSettingPage() public CustomizedSettingPage()
{ {
InitializeComponent(); InitializeComponent();
this.SetViewModel<CustomizedSettingPageVM>();
} }
} }

View File

@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using VPet.Solution.ViewModels.SettingEditor;
namespace VPet.Solution.Views.SettingEditor; namespace VPet.Solution.Views.SettingEditor;
@ -20,8 +21,11 @@ namespace VPet.Solution.Views.SettingEditor;
/// </summary> /// </summary>
public partial class DiagnosticSettingPage : Page public partial class DiagnosticSettingPage : Page
{ {
public DiagnosticSettingPageVM ViewModel => (DiagnosticSettingPageVM)DataContext;
public DiagnosticSettingPage() public DiagnosticSettingPage()
{ {
InitializeComponent(); InitializeComponent();
this.SetViewModel<DiagnosticSettingPageVM>();
} }
} }

View File

@ -52,9 +52,8 @@
<pu:Switch <pu:Switch
x:Name="PetHelperBox" x:Name="PetHelperBox"
Grid.Column="3" Grid.Column="3"
d:Checked="PetHelperBox_Checked"
d:Unchecked="PetHelperBox_Checked"
Content="{ll:Str '快速切换'}" Content="{ll:Str '快速切换'}"
IsChecked="{Binding GraphicsSetting.PetHelper}"
Style="{DynamicResource Switch_BaseStyle}" Style="{DynamicResource Switch_BaseStyle}"
ToolTip="{ll:Str '添加快速切换小标,切换顶层或穿透'}" /> ToolTip="{ll:Str '添加快速切换小标,切换顶层或穿透'}" />
</Grid> </Grid>
@ -153,7 +152,8 @@
ToolTip="{ll:Str '桌宠图形渲染的分辨率,越高图形越清晰\&#13;但是高分辨率会占用更多内存\&#13;重启后生效'}" ToolTip="{ll:Str '桌宠图形渲染的分辨率,越高图形越清晰\&#13;但是高分辨率会占用更多内存\&#13;重启后生效'}"
Value="{Binding Value, ElementName=Slider_Resolution}" /> Value="{Binding Value, ElementName=Slider_Resolution}" />
</Grid> </Grid>
<Grid MinHeight="40"> <!-- 实际上主题并没有实装 -->
<!--<Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition /> <ColumnDefinition />
@ -169,7 +169,7 @@
IsEnabled="False" IsEnabled="False"
SelectedItem="{Binding GraphicsSetting.Theme}" SelectedItem="{Binding GraphicsSetting.Theme}"
Style="{DynamicResource ComboBox_BaseStyle}" /> Style="{DynamicResource ComboBox_BaseStyle}" />
</Grid> </Grid>-->
<Grid MinHeight="40"> <Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@ -223,11 +223,12 @@
Value="{Binding GraphicsSetting.StartRecordPoint.Y}" /> Value="{Binding GraphicsSetting.StartRecordPoint.Y}" />
</DockPanel> </DockPanel>
<Button <Button
x:Name="BtnStartUpGet" x:Name="Button_StartPoint"
Grid.Column="4" Grid.Column="4"
d:Click="BtnStartUpGet_Click" Click="Button_StartPoint_Click"
Content="{ll:Str 设为当前位置}" Content="{ll:Str 设为当前位置}"
Style="{DynamicResource Button_BaseStyle}" /> Style="{DynamicResource Button_BaseStyle}"
ToolTip="{ll:Str 设为当前窗口左上角顶点坐标的位置}" />
</Grid> </Grid>
<Grid MinHeight="40"> <Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@ -242,9 +243,8 @@
<pu:Switch <pu:Switch
x:Name="SwitchMsgOut" x:Name="SwitchMsgOut"
Grid.Column="1" Grid.Column="1"
d:Checked="SwitchMsgOut_Checked"
d:Unchecked="SwitchMsgOut_Checked"
Content="{ll:Str 将消息框置于外部}" Content="{ll:Str 将消息框置于外部}"
IsChecked="{Binding GraphicsSetting.MessageBarOutside}"
Style="{DynamicResource Switch_BaseStyle}" Style="{DynamicResource Switch_BaseStyle}"
ToolTip="{ll:Str 将消息框置于外部}" /> ToolTip="{ll:Str 将消息框置于外部}" />
</Grid> </Grid>

View File

@ -29,4 +29,12 @@ public partial class GraphicsSettingPage : Page
InitializeComponent(); InitializeComponent();
this.SetViewModel<GraphicsSettingPageVM>(); this.SetViewModel<GraphicsSettingPageVM>();
} }
private void Button_StartPoint_Click(object sender, RoutedEventArgs e)
{
ViewModel.GraphicsSetting.StartRecordPoint = new(
SettingWindow.Instance.Left,
SettingWindow.Instance.Top
);
}
} }

View File

@ -24,7 +24,8 @@
FontSize="16" FontSize="16"
FontWeight="Bold" FontWeight="Bold"
Style="{DynamicResource Label_BaseStyle}" /> Style="{DynamicResource Label_BaseStyle}" />
<Grid MinHeight="40"> <!-- 存档才有这个设置 -->
<!--<Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition /> <ColumnDefinition />
@ -35,7 +36,7 @@
Grid.Column="1" Grid.Column="1"
Style="{DynamicResource StandardTextBoxStyle}" Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding InteractiveSetting.PetName}" /> Text="{Binding InteractiveSetting.PetName}" />
</Grid> </Grid>-->
<Grid MinHeight="40"> <Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@ -47,23 +48,19 @@
x:Name="Switch_EnablePetState" x:Name="Switch_EnablePetState"
Grid.Column="1" Grid.Column="1"
Content="{ll:Str '启用桌宠状态'}" Content="{ll:Str '启用桌宠状态'}"
IsChecked="{Binding InteractiveSetting.CalFunState}" IsChecked="{Binding InteractiveSetting.EnableFunction}"
Style="{DynamicResource Switch_BaseStyle}" Style="{DynamicResource Switch_BaseStyle}"
ToolTip="{ll:Str '启用数据计算,桌宠会有状态变化,需要按时投喂等.\&#13;如果嫌麻烦可以关掉'}" /> ToolTip="{ll:Str '启用数据计算,桌宠会有状态变化,需要按时投喂等.\&#13;如果嫌麻烦可以关掉'}" />
<!-- TODO: ComboBox使用内部数据 --> <!-- TODO: ComboBox使用内部数据 -->
<ComboBox <ComboBox
Grid.Column="2" Grid.Column="2"
Margin="0,5,10,5"
pu:ComboBoxHelper.Watermark="{ll:Str '当关闭数据计算时\&#13;桌宠显示的状态'}" pu:ComboBoxHelper.Watermark="{ll:Str '当关闭数据计算时\&#13;桌宠显示的状态'}"
IsEnabled="{Binding IsChecked, ElementName=Switch_EnablePetState, Converter={StaticResource BoolInverter}}" IsEnabled="{Binding IsChecked, ElementName=Switch_EnablePetState, Converter={StaticResource BoolInverter}}"
SelectedIndex="0" ItemsSource="{Binding InteractiveSetting.ModeTypes}"
SelectedItem="{Binding InteractiveSetting.CalFunState}" SelectedItem="{Binding InteractiveSetting.CalFunState}"
Style="{DynamicResource ComboBox_BaseStyle}" Style="{DynamicResource ComboBox_BaseStyle}"
ToolTip="{ll:Str '当关闭数据计算时\&#13;桌宠显示的状态'}"> ToolTip="{ll:Str '当关闭数据计算时\&#13;桌宠显示的状态'}" />
<ComboBoxItem Content="Happy" />
<ComboBoxItem Content="Nomal" />
<ComboBoxItem Content="PoorCondition" />
<ComboBoxItem Content="Ill" />
</ComboBox>
</Grid> </Grid>
<Grid MinHeight="40"> <Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@ -77,26 +74,26 @@
x:Name="PressLengthSlider" x:Name="PressLengthSlider"
Grid.Column="1" Grid.Column="1"
VerticalAlignment="Center" VerticalAlignment="Center"
d:ValueChanged="PressLengthSlider_ValueChanged"
LargeChange="0.1" LargeChange="0.1"
Maximum="5" Maximum="5"
Minimum="0.05" Minimum="0.5"
SmallChange=".05" SmallChange="0.5"
Style="{DynamicResource Slider_BaseStyle}" Style="{DynamicResource Slider_BaseStyle}"
TickFrequency="0.01" TickFrequency="0.5"
Value="0.5" /> Value="{Binding InteractiveSetting.PressLength}" />
<pu:NumberInput <pu:NumberInput
Grid.Column="2" Grid.Column="2"
MinWidth="80"
Interval="0.1" Interval="0.1"
Maximum="5" Maximum="5"
Minimum="0.05" Minimum="0.05"
Style="{DynamicResource NumberInput_BaseStyle}" Style="{DynamicResource NumberInput_BaseStyle}"
Value="{Binding Value, ElementName=PressLengthSlider}" /> Value="{Binding Value, ElementName=PressLengthSlider}" />
<TextBlock <Label
Grid.Column="3" Grid.Column="3"
Margin="0,5,10,5" Margin="0,5,10,5"
Style="{DynamicResource TextBlock_BaseStyle}" Content="{ll:Str 秒}"
Text="{ll:Str 秒}" /> Style="{DynamicResource Label_BaseStyle}" />
</Grid> </Grid>
<Grid MinHeight="40"> <Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@ -110,26 +107,26 @@
x:Name="Slider_Cal" x:Name="Slider_Cal"
Grid.Column="1" Grid.Column="1"
VerticalAlignment="Center" VerticalAlignment="Center"
d:ValueChanged="CalSlider_ValueChanged"
LargeChange="1" LargeChange="1"
Maximum="60" Maximum="60"
Minimum="5" Minimum="5"
SmallChange=".5" SmallChange="0.5"
Style="{DynamicResource Slider_BaseStyle}" Style="{DynamicResource Slider_BaseStyle}"
TickFrequency="0.1" TickFrequency="0.1"
Value="15" /> Value="{Binding InteractiveSetting.LogicInterval}" />
<pu:NumberInput <pu:NumberInput
Grid.Column="2" Grid.Column="2"
MinWidth="80"
Interval="0.5" Interval="0.5"
Maximum="60" Maximum="60"
Minimum="5" Minimum="5"
Style="{DynamicResource NumberInput_BaseStyle}" Style="{DynamicResource NumberInput_BaseStyle}"
Value="{Binding Value, ElementName=Slider_Cal}" /> Value="{Binding Value, ElementName=Slider_Cal}" />
<TextBlock <Label
Grid.Column="3" Grid.Column="3"
Margin="0,5,10,5" Margin="0,5,10,5"
Style="{DynamicResource TextBlock_BaseStyle}" Content="{ll:Str 秒}"
Text="{ll:Str 秒}" /> Style="{DynamicResource Label_BaseStyle}" />
</Grid> </Grid>
<Grid MinHeight="40" ToolTip="{ll:Str 互动周期决定在交互结束后大约经历多少计算间隔后再次进行自主行动}"> <Grid MinHeight="40" ToolTip="{ll:Str 互动周期决定在交互结束后大约经历多少计算间隔后再次进行自主行动}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@ -149,7 +146,7 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Slider <Slider
x:Name="Slider_Interaction" x:Name="Slider_Interaction"
d:ValueChanged="Slider_Interaction_ValueChanged" d:Value="1000"
LargeChange="5" LargeChange="5"
Maximum="1000" Maximum="1000"
Minimum="30" Minimum="30"
@ -157,19 +154,20 @@
Style="{DynamicResource Slider_BaseStyle}" Style="{DynamicResource Slider_BaseStyle}"
TickFrequency="1" TickFrequency="1"
ToolTip="{ll:Str '数据计算和互动计算时间间隔,间隔越短需要互动的频率可能会增加.\&#13;间隔越大越不容易打扰到当前工作'}" ToolTip="{ll:Str '数据计算和互动计算时间间隔,间隔越短需要互动的频率可能会增加.\&#13;间隔越大越不容易打扰到当前工作'}"
Value="200" /> Value="{Binding InteractiveSetting.InteractionCycle}" />
<pu:NumberInput <pu:NumberInput
Grid.Column="1" Grid.Column="1"
MinWidth="80"
Interval="1" Interval="1"
Maximum="1000" Maximum="1000"
Minimum="30" Minimum="30"
Style="{DynamicResource NumberInput_BaseStyle}" Style="{DynamicResource NumberInput_BaseStyle}"
Value="{Binding ElementName=Slider_Interaction, Path=Value}" /> Value="{Binding ElementName=Slider_Interaction, Path=Value}" />
<TextBlock <Label
Grid.Column="2" Grid.Column="2"
Margin="0,5,10,5" Margin="0,5,10,5"
Style="{DynamicResource TextBlock_BaseStyle}" Content="{ll:Str 秒}"
Text="{ll:Str 秒}" /> Style="{DynamicResource Label_BaseStyle}" />
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
@ -192,84 +190,32 @@
<pu:Switch <pu:Switch
x:Name="Switch_PetMove" x:Name="Switch_PetMove"
Grid.Column="1" Grid.Column="1"
d:Checked="Switch_PetMove_Checked"
d:Unchecked="Switch_PetMove_Checked"
Content="{ll:Str 启用桌宠移动}" Content="{ll:Str 启用桌宠移动}"
IsChecked="{Binding InteractiveSetting.AllowMove}"
Style="{DynamicResource Switch_BaseStyle}" Style="{DynamicResource Switch_BaseStyle}"
ToolTip="{ll:Str '启用移动互动,桌宠会在屏幕上乱动,移动互动概率为普通互动的一半.\&#13;如果嫌麻烦可以关掉'}" /> ToolTip="{ll:Str '启用移动互动,桌宠会在屏幕上乱动,移动互动概率为普通互动的一半.\&#13;如果嫌麻烦可以关掉'}" />
<pu:Switch <pu:Switch
x:Name="Switch_SmartPetMove" x:Name="Switch_SmartPetMove"
Grid.Column="2" Grid.Column="2"
d:Checked="SmartSwitch_PetMove_Checked"
d:Unchecked="SmartSwitch_PetMove_Checked"
Content="{ll:Str '智能移动'}" Content="{ll:Str '智能移动'}"
IsChecked="{Binding InteractiveSetting.SmartMove}"
IsEnabled="{Binding ElementName=Switch_PetMove, Path=IsChecked}" IsEnabled="{Binding ElementName=Switch_PetMove, Path=IsChecked}"
Style="{DynamicResource Switch_BaseStyle}" /> Style="{DynamicResource Switch_BaseStyle}" />
<ComboBox <ComboBox
x:Name="CBSmartMove" x:Name="CBSmartMove"
Grid.Column="3" Grid.Column="3"
d:SelectionChanged="CBSmartMove_SelectionChanged"
IsEnabled="{Binding IsChecked, ElementName=Switch_SmartPetMove}" IsEnabled="{Binding IsChecked, ElementName=Switch_SmartPetMove}"
SelectedIndex="5" ItemsSource="{Binding InteractiveSetting.SmartMoveIntervals}"
SelectedItem="{Binding InteractiveSetting.SmartMoveInterval}"
Style="{DynamicResource StandardComboBoxStyle}" Style="{DynamicResource StandardComboBoxStyle}"
ToolTip="{ll:Str 智能移动判断时间间隔}"> ToolTip="{ll:Str 智能移动判断时间间隔}" />
<!--<ComboBoxItem Content="{ll:Str '30 秒'}"> <Label
<ComboBoxItem.Tag>
<sys:Int32>30</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str '1 分钟'}">
<ComboBoxItem.Tag>
<sys:Int32>60</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str '2 分钟'}">
<ComboBoxItem.Tag>
<sys:Int32>120</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str '5 分钟'}">
<ComboBoxItem.Tag>
<sys:Int32>300</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str '10 分钟'}">
<ComboBoxItem.Tag>
<sys:Int32>600</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str '20 分钟'}">
<ComboBoxItem.Tag>
<sys:Int32>1200</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str '30 分钟'}">
<ComboBoxItem.Tag>
<sys:Int32>1800</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str '40 分钟'}">
<ComboBoxItem.Tag>
<sys:Int32>2400</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str '50 分钟'}">
<ComboBoxItem.Tag>
<sys:Int32>3000</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str '60 分钟'}">
<ComboBoxItem.Tag>
<sys:Int32>3600</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>-->
</ComboBox>
<TextBlock
Grid.Column="4" Grid.Column="4"
Style="{DynamicResource TextBlock_BaseStyle}" Content="{ll:Str 分钟}"
Text="{ll:Str 分钟}" /> Style="{DynamicResource Label_BaseStyle}" />
</Grid> </Grid>
<Grid MinHeight="40"> <!-- TODO: 移动范围设置 -->
<!--<Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition /> <ColumnDefinition />
@ -313,7 +259,7 @@
Style="{DynamicResource Button_BaseStyle}" Style="{DynamicResource Button_BaseStyle}"
ToolTip="{ll:Str '手动设置桌宠可移动范围'}" /> ToolTip="{ll:Str '手动设置桌宠可移动范围'}" />
</Grid> </Grid>
</Grid> </Grid>-->
<Label <Label
Margin="5" Margin="5"
HorizontalAlignment="Left" HorizontalAlignment="Left"
@ -335,7 +281,6 @@
<Slider <Slider
x:Name="VoiceCatchSilder" x:Name="VoiceCatchSilder"
Grid.Column="1" Grid.Column="1"
d:ValueChanged="VoiceCatchSilder_ValueChanged"
LargeChange="5" LargeChange="5"
Maximum="100" Maximum="100"
Minimum="0" Minimum="0"
@ -343,19 +288,21 @@
Style="{DynamicResource Slider_BaseStyle}" Style="{DynamicResource Slider_BaseStyle}"
TickFrequency="1" TickFrequency="1"
ToolTip="{ll:Str 当实时播放音量达到该值时运行音乐动作}" ToolTip="{ll:Str 当实时播放音量达到该值时运行音乐动作}"
Value="30" /> Value="{Binding InteractiveSetting.MusicCatch}" />
<pu:NumberInput <pu:NumberInput
Grid.Column="2" Grid.Column="2"
MinWidth="80"
Interval="1" Interval="1"
Maximum="100" Maximum="100"
Minimum="0" Minimum="0"
Style="{DynamicResource NumberInput_BaseStyle}" Style="{DynamicResource NumberInput_BaseStyle}"
ToolTip="{ll:Str 当实时播放音量达到该值时运行特殊音乐动作}" ToolTip="{ll:Str 当实时播放音量达到该值时运行特殊音乐动作}"
Value="{Binding Value, ElementName=VoiceCatchSilder}" /> Value="{Binding Value, ElementName=VoiceCatchSilder}" />
<TextBlock <Label
Grid.Column="3" Grid.Column="3"
Margin="0,5,10,5" Margin="0,5,10,5"
Text="%" /> Content="%"
Style="{DynamicResource Label_BaseStyle}" />
</Grid> </Grid>
<Grid MinHeight="40"> <Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@ -371,17 +318,17 @@
<Slider <Slider
x:Name="VoiceMaxSilder" x:Name="VoiceMaxSilder"
Grid.Column="1" Grid.Column="1"
d:ValueChanged="VoiceCatchSilder_ValueChanged"
LargeChange="1" LargeChange="1"
Maximum="100" Maximum="100"
Minimum="{Binding ElementName=VoiceCatchSilder, Path=Value}" Minimum="{Binding ElementName=VoiceCatchSilder, Path=Value}"
SmallChange="1" SmallChange="1"
Style="{DynamicResource StandardSliderStyle}" Style="{DynamicResource Slider_BaseStyle}"
TickFrequency="1" TickFrequency="1"
ToolTip="{ll:Str 当实时播放音量达到该值时运行特殊音乐动作}" ToolTip="{ll:Str 当实时播放音量达到该值时运行特殊音乐动作}"
Value="75" /> Value="{Binding InteractiveSetting.MusicMax}" />
<pu:NumberInput <pu:NumberInput
Grid.Column="2" Grid.Column="2"
MinWidth="80"
Foreground="{DynamicResource DARKPrimaryDarker}" Foreground="{DynamicResource DARKPrimaryDarker}"
Interval="1" Interval="1"
Maximum="100" Maximum="100"
@ -389,10 +336,11 @@
Style="{DynamicResource NumberInput_BaseStyle}" Style="{DynamicResource NumberInput_BaseStyle}"
ToolTip="{ll:Str 当实时播放音量达到该值时运行特殊音乐动作}" ToolTip="{ll:Str 当实时播放音量达到该值时运行特殊音乐动作}"
Value="{Binding Value, ElementName=VoiceMaxSilder}" /> Value="{Binding Value, ElementName=VoiceMaxSilder}" />
<TextBlock <Label
Grid.Column="3" Grid.Column="3"
Margin="0,5,10,5" Margin="0,5,10,5"
Text="%" /> Content="%"
Style="{DynamicResource Label_BaseStyle}" />
</Grid> </Grid>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>

View File

@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using VPet.Solution.ViewModels.SettingEditor;
namespace VPet.Solution.Views.SettingEditor; namespace VPet.Solution.Views.SettingEditor;
@ -20,8 +21,11 @@ namespace VPet.Solution.Views.SettingEditor;
/// </summary> /// </summary>
public partial class InteractiveSettingPage : Page public partial class InteractiveSettingPage : Page
{ {
public InteractiveSettingPageVM ViewModel => (InteractiveSettingPageVM)DataContext;
public InteractiveSettingPage() public InteractiveSettingPage()
{ {
InitializeComponent(); InitializeComponent();
this.SetViewModel<InteractiveSettingPageVM>();
} }
} }

View File

@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using VPet.Solution.ViewModels.SettingEditor;
namespace VPet.Solution.Views.SettingEditor; namespace VPet.Solution.Views.SettingEditor;
@ -20,8 +21,11 @@ namespace VPet.Solution.Views.SettingEditor;
/// </summary> /// </summary>
public partial class ModSettingPage : Page public partial class ModSettingPage : Page
{ {
public ModSettingPageVM ViewModel => (ModSettingPageVM)DataContext;
public ModSettingPage() public ModSettingPage()
{ {
InitializeComponent(); InitializeComponent();
this.SetViewModel<ModSettingPageVM>();
} }
} }

View File

@ -9,7 +9,7 @@
xmlns:pu="https://opensource.panuon.com/wpf-ui" xmlns:pu="https://opensource.panuon.com/wpf-ui"
xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:vm="clr-namespace:VPet.Solution.ViewModels.SettingEditor" xmlns:vm="clr-namespace:VPet.Solution.ViewModels.SettingEditor"
Title="{ll:Str 'VPET 问题解决工具'}" Title="{ll:Str 'VPET 设置编辑器'}"
Width="800" Width="800"
Height="450" Height="450"
MinWidth="400" MinWidth="400"
@ -29,7 +29,10 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBox Style="{DynamicResource StandardTextBoxStyle}" Text="{Binding SearchSetting, UpdateSourceTrigger=PropertyChanged}" /> <TextBox
pu:TextBoxHelper.Watermark="{ll:Str 搜索设置}"
Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding SearchSetting, UpdateSourceTrigger=PropertyChanged}" />
<ListBox <ListBox
x:Name="ListBox_Saves" x:Name="ListBox_Saves"
Grid.Row="1" Grid.Row="1"
@ -44,14 +47,22 @@
<Setter Property="ToolTip" Value="{Binding FilePath}" /> <Setter Property="ToolTip" Value="{Binding FilePath}" />
<Setter Property="ContextMenu"> <Setter Property="ContextMenu">
<Setter.Value> <Setter.Value>
<ContextMenu> <ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Mode=Self}}">
<MenuItem
Command="{Binding PlacementTarget.Tag.OpenFileCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}"
Header="{ll:Str 打开文件}" />
<MenuItem
Command="{Binding PlacementTarget.Tag.OpenFileInExplorerCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding}"
Header="{ll:Str 从资源管理器打开文件}" />
<MenuItem <MenuItem
Command="{Binding PlacementTarget.Tag.SaveSettingCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}" Command="{Binding PlacementTarget.Tag.SaveSettingCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}" CommandParameter="{Binding}"
Header="{ll:Str 保存}" /> Header="{ll:Str 保存}" />
<MenuItem <MenuItem
Command="{Binding PlacementTarget.Tag.ResetSettingCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}" Command="{Binding PlacementTarget.Tag.ResetSettingCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}" CommandParameter="{Binding}"
Header="{ll:Str 重置}" /> Header="{ll:Str 重置}" />
</ContextMenu> </ContextMenu>
</Setter.Value> </Setter.Value>

View File

@ -39,44 +39,9 @@
x:Name="CBAutoSave" x:Name="CBAutoSave"
Grid.Column="2" Grid.Column="2"
d:SelectionChanged="CBAutoSave_SelectionChanged" d:SelectionChanged="CBAutoSave_SelectionChanged"
SelectedIndex="3" ItemsSource="{Binding SystemSetting.SaveIntervals}"
Style="{DynamicResource ComboBox_BaseStyle}"> SelectedItem="{Binding SystemSetting.AutoSaveInterval}"
<!--<ComboBoxItem Content="{ll:Str 关闭自动保存}"> Style="{DynamicResource ComboBox_BaseStyle}" />
<ComboBoxItem.Tag>
<sys:Int32>-1</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str 每2分钟一次}">
<ComboBoxItem.Tag>
<sys:Int32>2</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str 每5分钟一次}">
<ComboBoxItem.Tag>
<sys:Int32>5</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str 每10分钟一次}">
<ComboBoxItem.Tag>
<sys:Int32>10</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str 每20分钟一次}">
<ComboBoxItem.Tag>
<sys:Int32>20</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str 每半小时一次}">
<ComboBoxItem.Tag>
<sys:Int32>30</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>
<ComboBoxItem Content="{ll:Str 每小时一次}">
<ComboBoxItem.Tag>
<sys:Int32>60</sys:Int32>
</ComboBoxItem.Tag>
</ComboBoxItem>-->
</ComboBox>
<TextBlock <TextBlock
Grid.Column="3" Grid.Column="3"
Style="{DynamicResource TextBlock_BaseStyle}" Style="{DynamicResource TextBlock_BaseStyle}"

View File

@ -12,6 +12,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using VPet.Solution.ViewModels.SettingEditor;
namespace VPet.Solution.Views.SettingEditor; namespace VPet.Solution.Views.SettingEditor;
@ -20,8 +21,11 @@ namespace VPet.Solution.Views.SettingEditor;
/// </summary> /// </summary>
public partial class SystemSettingPage : Page public partial class SystemSettingPage : Page
{ {
public SystemSettingPageVM ViewModel => (SystemSettingPageVM)DataContext;
public SystemSettingPage() public SystemSettingPage()
{ {
InitializeComponent(); InitializeComponent();
this.SetViewModel<SystemSettingPageVM>();
} }
} }