mirror of
https://github.com/LorisYounger/VPet.git
synced 2024-08-30 18:42:36 +00:00
Merge branch 'main' of https://github.com/LorisYounger/VPet
This commit is contained in:
commit
75799da51a
@ -1,4 +1,4 @@
|
||||
简体中文 | [English](./CONTRIBUTING_en.md)
|
||||
简体中文 | [繁體中文](./CONTRIBUTING_zht.md) | [English](./CONTRIBUTING_en.md)
|
||||
|
||||
## 参与开发
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Contributing
|
||||
|
||||
[简体中文](./CONTRIBUTING.md) | English
|
||||
[简体中文](./CONTRIBUTING.md) | [繁體中文](./CONTRIBUTING_zht.md) | English
|
||||
|
||||
Welcome to participate in development! To ensure code maintainability and playability, if you wish to develop new features or gameplay, please first contact me (by sending a [mail](mailto:zoujin.dev@exlb.org) or opening an [Issue](https://github.com/LorisYounger/VPet/issues/new)) with your idea. This is to make sure your contribution fits the game, and will not get outright rejected for being unfitting (causing your effort to be wasted). You don't need to contact me regarding fixing errors or bugs - simply send a PR in that case.
|
||||
|
||||
@ -88,4 +88,4 @@ You **must** inform users of the source of our animation files, and provide a li
|
||||
|
||||
* All of the above authorization information **must** be disclosed.
|
||||
* You **must** provide a link to [this page](https://github.com/LorisYounger/VPet).
|
||||
* **No** profit should be made with our files.
|
||||
* **No** profit should be made with our files.
|
||||
|
89
CONTRIBUTING_zht.md
Normal file
89
CONTRIBUTING_zht.md
Normal file
@ -0,0 +1,89 @@
|
||||
[简体中文](./CONTRIBUTING.md) | 繁體中文 | [English](./CONTRIBUTING_en.md)
|
||||
|
||||
## 參與開發
|
||||
|
||||
歡迎參與虛擬桌寵模擬器的開發!為了保證程式碼的可維護性及遊戲性,若想要開發新的功能,請先[電子郵件聯絡](mailto:zoujin.dev@exlb.org)或提交[Issue](https://github.com/LorisYounger/VPet/issues),標題為想要新增的功能/玩法,以確保該功能/玩法適用於虛擬桌寵模擬器,以免在您完成開發後,因不適合而被拒絕(而浪費您的時間)。<br/>
|
||||
如果是修正錯誤或BUG,則不需要先行聯絡,修好後直接提交即可。
|
||||
|
||||
當您提供的想法被贊同後,您可以使用[Fork](https://github.com/LorisYounger/VPet/fork)功能,將專案程式碼整個複製至個人的Github上,以便撰寫自己的程式碼。撰寫完畢後,使用[Pull Requests](https://github.com/LorisYounger/VPet/compare)提交。<br/>
|
||||
若您的想法並未被同意,也可以另起爐灶,開發一個不同版本及功能的桌寵軟體。須遵守[Apache License 2.0](https://github.com/LorisYounger/VPet/blob/main/LICENSE)及[動畫版權聲明與授權](https://github.com/LorisYounger/VPet/blob/main/README_zht.md#%E5%8B%95%E7%95%AB%E7%89%88%E6%AC%8A%E8%81%B2%E6%98%8E%E8%88%87%E6%8E%88%E6%AC%8A)。<br/>
|
||||
註:一般而言,加入新功能都可以透過撰寫模組來達成,詳情請見:[VPet.Plugin.Demo](https://github.com/LorisYounger/VPet.Plugin.Demo)
|
||||
|
||||
作者可能會修改、刪減部分您所提交的程式碼,以確保該功能/玩法適用於虛擬桌寵模擬器。
|
||||
|
||||
## 動畫版權聲明與授權
|
||||
|
||||
在Github中,[桌寵動畫檔案](https://github.com/LorisYounger/VPet/tree/main/VPet-Simulator.Windows/mod/0000_core/pet/vup)之動畫版權歸[虛擬主播模擬器製作組](https://www.exlb.net/VUP-Simulator)所有,在使用本類別庫時,您可能會需要自行準備動畫檔,或遵循下列協定:
|
||||
|
||||
### 非商業用途授權
|
||||
|
||||
* 需要向使用者告知動畫檔案的來源,並提供造訪[本頁面](https://github.com/LorisYounger/VPet)的連結
|
||||
* 當您完成上述要求後,可以免費使用動畫檔案
|
||||
|
||||
### 商業用途授權(低於10萬)
|
||||
|
||||
* 在使用者第一次使用時,需跳出視窗,並醒目向使用者告知動畫檔案的來源,並提供造訪[本頁面](https://github.com/LorisYounger/VPet)的連結
|
||||
* 在對應的頁面上(使用者能快速造訪的),向使用者告知動畫檔案的來源,並提供造訪[本頁面](https://github.com/LorisYounger/VPet)的連結
|
||||
* 當您完成上述要求後,可以免費使用動畫檔案
|
||||
|
||||
### 商業用途授權(高於10萬或其他)
|
||||
|
||||
* 請[電子郵件聯絡](mailto:zoujin.dev@exlb.org)本軟體作者
|
||||
|
||||
### 轉發動畫檔案
|
||||
|
||||
* 需要告知上述所有授權資訊
|
||||
* 需要提供造訪[本頁面](https://github.com/LorisYounger/VPet)的連結
|
||||
* 轉發動畫檔案時,禁止任何付費或收費行為
|
||||
|
||||
## 桌面應用程式部署方式
|
||||
|
||||
1. 下載本專案,透過VisualStudio開啟`VPet.sln`檔案
|
||||
2. 在「建置」選項中,選擇位元數`x64`及建置專案`Vpet-Simulator.Windows`
|
||||
![image-20230208004330895](README.assets/image-20230208004330895.png)
|
||||
3. 點擊「開始」,若一切順利將會報錯`缺少Core模組,無法啟動桌寵`
|
||||
4. 以管理員身分執行`mklink.bat`,這會讓模組檔案連結至產生的位置
|
||||
5. 再次點擊啟動即可正常執行
|
||||
|
||||
## 軟體架構
|
||||
|
||||
* **VPet-Simulator.Windows: 適用於桌面端的虛擬桌寵模擬器**
|
||||
* *Function 功能性程式碼儲存位置*
|
||||
* CoreMOD 模組管理
|
||||
* MWController 視窗控制器
|
||||
|
||||
* *WinDesign 視窗及UI設計
|
||||
* winBetterBuy 更好買視窗
|
||||
* winCGPTSetting ChatGPT設定
|
||||
* winSetting 軟體設定、模組視窗
|
||||
* winConsole 開發控制台
|
||||
* winGameSetting 遊戲設定
|
||||
* winReport 意見回饋中心
|
||||
|
||||
* MainWindows 主視窗、儲存及展示Core
|
||||
* PetHelper 快速切換圖示
|
||||
* **VPet-Simulator.Tool: 方便製作模組的工具(例如:產生動態圖片)**
|
||||
* **VPet-Simulator.Core: 軟體核心,方便內建至任何的WPF應用程式(例如:VUP-Simulator)**
|
||||
* Handle 介面及控制項
|
||||
* IController 視窗控制(呼叫相關功能及設定,例如:移動到側邊等)
|
||||
* Function 通用功能
|
||||
* GameCore 遊戲核心,包含各種資料數據等內容
|
||||
* GameSave 遊戲存檔
|
||||
* IFood 食物及物品介面
|
||||
* PetLoader 寵物圖片載入器
|
||||
* Graph 圖形渲染
|
||||
* IGraph 動畫基本介面
|
||||
* GraphCore 動畫顯示核心
|
||||
* GraphHelper 動畫幫助
|
||||
* GraphInfo 動畫資訊
|
||||
* FoodAnimation 食物動畫,支援顯示前中後三層夾心動畫,不一定只用於食物,只是叫這個名字
|
||||
* PNGAnimation 桌寵動態動畫元件
|
||||
* Picture 桌寵靜態動畫元件
|
||||
* Display 顯示
|
||||
* basestyle/Theme 基礎風格主題
|
||||
* Main.xaml 核心顯示元件
|
||||
* MainDisplay 核心顯示方法
|
||||
* MainLogic 核心顯示邏輯
|
||||
* ToolBar 點擊人物時的工具欄
|
||||
* MessageBar 人物說話時的對話框
|
||||
* WorkTimer 運作計時器
|
@ -9,6 +9,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Xml.Linq;
|
||||
using VPet_Simulator.Core;
|
||||
using VPet_Simulator.Windows.Interface;
|
||||
|
||||
@ -104,6 +105,13 @@ namespace VPet_Simulator.Windows
|
||||
LocalizeCore.AddCulture(line.info, ls);
|
||||
}
|
||||
|
||||
if (mw.CoreMODs.FirstOrDefault(x => x.Name == Name) != null)
|
||||
{
|
||||
Name += $"({"MOD名称重复".Translate()})";
|
||||
ErrorMessage = "MOD名称重复".Translate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsOnMOD(mw))
|
||||
{
|
||||
Tag.Add("该模组已停用");
|
||||
@ -155,6 +163,8 @@ namespace VPet_Simulator.Windows
|
||||
var tmp = new LpsDocument(File.ReadAllText(fi.FullName));
|
||||
foreach (ILine li in tmp)
|
||||
{
|
||||
if (li.Name != "food")
|
||||
continue;
|
||||
string tmps = li.Find("name").info;
|
||||
mw.Foods.RemoveAll(x => x.Name == tmps);
|
||||
mw.Foods.Add(LPSConvert.DeserializeObject<Food>(li));
|
||||
|
@ -1205,6 +1205,7 @@ namespace VPet_Simulator.Windows
|
||||
public async void GameLoad(List<DirectoryInfo> Path)
|
||||
{
|
||||
|
||||
Path = Path.Distinct().ToList();
|
||||
await Dispatcher.InvokeAsync(new Action(() => LoadingText.Content = "Loading MOD"));
|
||||
//加载mod
|
||||
foreach (DirectoryInfo di in Path)
|
||||
|
@ -353,6 +353,8 @@ namespace VPet_Simulator.Windows
|
||||
|
||||
private void pagination_CurrentPageChanged(object sender, SelectedValueChangedRoutedEventArgs<int> e)
|
||||
{
|
||||
if (!AllowChange)
|
||||
return;
|
||||
Search();
|
||||
TbPage.Text = e.NewValue.ToString();
|
||||
}
|
||||
|
@ -1,3 +1,9 @@
|
||||
food:|name#莲蓉蛋黄月饼:|type#Snack:|Exp#100:|Strength#40:|StrengthDrink#-3:|StrengthFood#80:|Likability#1:|Health#5:|Feeling#40:|price#26:|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#Snack:|Exp#100:|Strength#40:|StrengthDrink#-3:|StrengthFood#80:|Likability#1:|Health#5:|Feeling#40:|price#26:|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#Gift:|Exp#200:|Likability#4:|Health#5:|Feeling#50:|price#40.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#Drink:|Exp#200:|StrengthDrink#80:|Likability#2:|Feeling#60:|price#35:|graph#drink:|desc#圣诞草莓奶茶_giftintor:|
|
||||
food:|name#萝莉丝姜饼人:|type#Snack:|Exp#600:|StrengthFood#80:|Likability#2:|Health#2:|Feeling#50:|price#128.0:|graph#eat:|desc#萝莉丝姜饼人_giftintor:|
|
||||
|
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/圣诞帽.png
Normal file
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/圣诞帽.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/圣诞草莓奶茶.png
Normal file
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/圣诞草莓奶茶.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/礼物盒子.png
Normal file
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/礼物盒子.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/糖果棒.png
Normal file
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/糖果棒.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/萝莉丝姜饼人.png
Normal file
BIN
VPet-Simulator.Windows/mod/0000_core/image/food/萝莉丝姜饼人.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@ -7,4 +7,14 @@
|
||||
主人,sbeam秋季促销开始了哦,还有游戏大奖赛,快去给{name}去投一票吧。#Master, Sbeam's autumn promotion has begun, and there is also a Awards . Go and vote for {name}.:|
|
||||
主人主人,{name}参加了sbeam大奖赛哦,给人家投一票喵#Master, {name} is participating in the Sbeam Awards , vote for me meow:|
|
||||
那个。。主人。。\n人家参加了sbeam大奖赛哦。能不能。。给{name}投一票呢~#That... Master... I'm participating in the Sbeam Awards . Can you... vote for {name}~:|
|
||||
电脑里有一款《虚拟桌宠模拟器》的游戏正在参加2023的sbeam大奖赛,快来给桌宠投一票吧#There is a game called "VPet Simulator" in the computer that is participating in the 2023 Sbeam Awards , come and vote for the desktop pet:|
|
||||
电脑里有一款《虚拟桌宠模拟器》的游戏正在参加2023的sbeam大奖赛,快来给桌宠投一票吧#There is a game called "VPet Simulator" in the computer that is participating in the 2023 Sbeam Awards , come and vote for the desktop pet:|
|
||||
圣诞帽#Christmas hat:|
|
||||
圣诞帽_giftintor#An ordinary hat, but anyone can be Santa with it.:|
|
||||
礼物盒子#Gift box:|
|
||||
礼物盒子_giftintor#Surprise!!:|
|
||||
糖果棒#Candy bar:|
|
||||
糖果棒_giftintor#You can eat it, play with it, and use it to spank bad kids.:|
|
||||
圣诞草莓奶茶#Christmas strawberry milk tea:|
|
||||
圣诞草莓奶茶_giftintor#I don't know why it's Christmas cream tea and not Christmas cake, maybe the artist likes Christmas strawberry cream tea:|
|
||||
萝莉丝姜饼人#Gingerbread Lolis:|
|
||||
萝莉丝姜饼人_giftintor#Lolis made her own gingerbread man, and Lolis would get mad if she couldn't eat it because it was too cute!:|
|
@ -0,0 +1 @@
|
||||
MOD名称重复#MOD name duplicated:|
|
@ -4,7 +4,17 @@
|
||||
海上生明月,天涯共此时。无论近况如何,前途多难,计划如不如意,未来迷不迷茫,萝莉丝都为你做了莲蓉蛋黄月饼,快说谢谢萝莉丝。#海上生明月,天涯共此时。无论近况如何,前途多难,计划如不如意,未来迷不迷茫,萝莉丝都为你做了莲蓉蛋黄月饼,快说谢谢萝莉丝。:|
|
||||
巧克力花生月饼#巧克力花生月饼:|
|
||||
明月几时有,把酒问青天。无论考的如何,作业有多少,老师怎么说,家长怎么批评,萝莉丝都为你做了巧克力花生月饼,快说谢谢萝莉丝。#明月几时有,把酒问青天。无论考的如何,作业有多少,老师怎么说,家长怎么批评,萝莉丝都为你做了巧克力花生月饼,快说谢谢萝莉丝。:|
|
||||
主人,sbema秋季促销开始了哦,还有游戏大奖赛,快去给{name}去投一票吧。
|
||||
主人主人,{name}参加了sbeam大奖赛哦,给人家投一票喵
|
||||
那个。。主人。。\n人家参加了sbeam大奖赛哦。能不能。。给{name}投一票呢~
|
||||
电脑里有一款《虚拟桌宠模拟器》的游戏正在参加2023的sbeam大奖赛,快来给桌宠投一票吧
|
||||
主人,sbema秋季促销开始了哦,还有游戏大奖赛,快去给{name}去投一票吧。#主人,sbema秋季促销开始了哦,还有游戏大奖赛,快去给{name}去投一票吧。:|
|
||||
主人主人,{name}参加了sbeam大奖赛哦,给人家投一票喵#主人主人,{name}参加了sbeam大奖赛哦,给人家投一票喵:|
|
||||
那个。。主人。。\n人家参加了sbeam大奖赛哦。能不能。。给{name}投一票呢~#那个。。主人。。\n人家参加了sbeam大奖赛哦。能不能。。给{name}投一票呢~:|
|
||||
电脑里有一款《虚拟桌宠模拟器》的游戏正在参加2023的sbeam大奖赛,快来给桌宠投一票吧#电脑里有一款《虚拟桌宠模拟器》的游戏正在参加2023的sbeam大奖赛,快来给桌宠投一票吧:|
|
||||
圣诞帽#圣诞帽:|
|
||||
圣诞帽_giftintor#一顶普通的帽子,但带上它谁都可以成为圣诞老人:|
|
||||
礼物盒子#礼物盒子:|
|
||||
礼物盒子_giftintor#Surprise!!:|
|
||||
糖果棒#糖果棒:|
|
||||
糖果棒_giftintor#能吃能玩,还能用来打坏小孩的屁股:|
|
||||
圣诞草莓奶茶#圣诞草莓奶茶:|
|
||||
圣诞草莓奶茶_giftintor#我不知道为什么是圣诞奶茶而不是圣诞蛋糕,可能画师喜欢圣诞草莓奶茶吧:|
|
||||
萝莉丝姜饼人#萝莉丝姜饼人:|
|
||||
萝莉丝姜饼人_giftintor#萝莉丝做的自己样子的姜饼人,要是因为太可爱舍不得吃萝莉丝会生气的哦:|
|
@ -0,0 +1 @@
|
||||
MOD名称重复#MOD名称重复:|
|
@ -7,4 +7,14 @@
|
||||
主人,sbeam秋季促销开始了哦,还有游戏大奖赛,快去给{name}去投一票吧。#主人,sbeam秋季促銷開始了哦,還有遊戲大獎賽,快去給{name}去投一票吧。:|
|
||||
主人主人,{name}参加了sbeam大奖赛哦,给人家投一票喵#主人主人,{name}參加了sbeam大獎賽哦,給人家投一票喵:|
|
||||
那个。。主人。。\n人家参加了sbeam大奖赛哦。能不能。。给{name}投一票呢~#那個。。主人。。\n人家參加了sbeam大獎賽哦。能不能。。給{name}投一票呢~:|
|
||||
电脑里有一款《虚拟桌宠模拟器》的游戏正在参加2023的sbeam大奖赛,快来给桌宠投一票吧#電腦裡有一款《虛擬桌寵模擬器》的遊戲正在參加2023的sbeam大獎賽,快來給桌寵投一票吧:|
|
||||
电脑里有一款《虚拟桌宠模拟器》的游戏正在参加2023的sbeam大奖赛,快来给桌宠投一票吧#電腦裡有一款《虛擬桌寵模擬器》的遊戲正在參加2023的sbeam大獎賽,快來給桌寵投一票吧:|
|
||||
圣诞帽#聖誕帽:|
|
||||
圣诞帽_giftintor#一頂普通的帽子,但帶上它誰都可以成為聖誕老人:|
|
||||
礼物盒子#禮物盒子:|
|
||||
礼物盒子_giftintor#Surprise!!:|
|
||||
糖果棒#糖果棒:|
|
||||
糖果棒_giftintor#能吃能玩,還能用來打壞小孩的屁股:|
|
||||
圣诞草莓奶茶#聖誕草莓奶茶:|
|
||||
圣诞草莓奶茶_giftintor#我不知道為什麼是聖誕奶茶而不是聖誕蛋糕,可能畫師喜歡聖誕草莓奶茶吧:|
|
||||
萝莉丝姜饼人#蘿莉斯薑餅人:|
|
||||
萝莉丝姜饼人_giftintor#蘿莉絲做的自己樣子的薑餅人,要是因為太可愛捨不得吃蘿莉絲會生氣的哦:|
|
||||
|
@ -0,0 +1 @@
|
||||
MOD名称重复#MOD名稱重複:|
|
@ -1,9 +1,17 @@
|
||||
<Application x:Class="VPet.Solution.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:VPet.Solution"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
<Application
|
||||
x:Class="VPet.Solution.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="Views/MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="/VPet-Simulator.Windows.Interface;component/ResourceStyle.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/Panuon.WPF.UI;component/Control.xaml" />
|
||||
<ResourceDictionary Source="Converters.xaml" />
|
||||
<ResourceDictionary Source="Templates.xaml" />
|
||||
<ResourceDictionary Source="Styles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
@ -1,42 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using VPet_Simulator.Windows.Interface;
|
||||
|
||||
namespace VPet.Solution
|
||||
namespace VPet.Solution;
|
||||
|
||||
/// <summary>
|
||||
/// App.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
/// <summary>
|
||||
/// App.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
public static bool IsDone { get; set; } = false;
|
||||
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
public static bool IsDone { get; set; } = false;
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
if (e.Args != null && e.Args.Count() > 0)
|
||||
{
|
||||
if (e.Args != null && e.Args.Count() > 0)
|
||||
IsDone = true;
|
||||
switch (e.Args[0].ToLower())
|
||||
{
|
||||
IsDone = true;
|
||||
switch (e.Args[0].ToLower())
|
||||
{
|
||||
case "removestarup":
|
||||
var path = Environment.GetFolderPath(Environment.SpecialFolder.Startup) + @"\VPET_Simulator.lnk";
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
return;
|
||||
case "launchsteam":
|
||||
Process.Start("steam://rungameid/1920960");
|
||||
return;
|
||||
}
|
||||
case "removestarup":
|
||||
var path =
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.Startup)
|
||||
+ @"\VPET_Simulator.lnk";
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
return;
|
||||
case "launchsteam":
|
||||
Process.Start("steam://rungameid/1920960");
|
||||
return;
|
||||
}
|
||||
IsDone = false;
|
||||
}
|
||||
IsDone = false;
|
||||
}
|
||||
}
|
||||
|
16
VPet.Solution/Converters.xaml
Normal file
16
VPet.Solution/Converters.xaml
Normal file
@ -0,0 +1,16 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:c="clr-namespace:VPet.House.Converters">
|
||||
<c:MarginConverter x:Key="MarginConverter" />
|
||||
<c:RatioMarginConverter x:Key="RatioMarginConverter" />
|
||||
<c:CalculatorConverter x:Key="CalculatorConverter" />
|
||||
<c:StringFormatConverter x:Key="StringFormatConverter" />
|
||||
<c:BrushToMediaColorConverter x:Key="BrushToMediaColorConverter" />
|
||||
<c:MaxConverter x:Key="MaxConverter" />
|
||||
<c:FalseToHiddenConverter x:Key="FalseToHiddenConverter" />
|
||||
<c:EqualsConverter x:Key="EqualsConverter" />
|
||||
<c:NotEqualsConverter x:Key="NotEqualsConverter" />
|
||||
<c:NullToFalseConverter x:Key="NullToFalseConverter" />
|
||||
<c:BoolInverter x:Key="BoolInverter" />
|
||||
</ResourceDictionary>
|
19
VPet.Solution/Converters/BoolInverter.cs
Normal file
19
VPet.Solution/Converters/BoolInverter.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
public class BoolInverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not bool b)
|
||||
return false;
|
||||
return !b;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
22
VPet.Solution/Converters/BrushToMediaColorConverter.cs
Normal file
22
VPet.Solution/Converters/BrushToMediaColorConverter.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
public class BrushToMediaColorConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not SolidColorBrush brush)
|
||||
throw new ArgumentException("Not SolidColorBrush", nameof(value));
|
||||
return brush.Color;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not Color color)
|
||||
throw new ArgumentException("Not media color", nameof(value));
|
||||
return new SolidColorBrush(color);
|
||||
}
|
||||
}
|
97
VPet.Solution/Converters/CalculatorConverter.cs
Normal file
97
VPet.Solution/Converters/CalculatorConverter.cs
Normal file
@ -0,0 +1,97 @@
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
/// <summary>
|
||||
/// 计算器转换器
|
||||
/// <para>示例:
|
||||
/// <code><![CDATA[
|
||||
/// <MultiBinding Converter="{StaticResource CalculatorConverter}">
|
||||
/// <Binding Path="Num1" />
|
||||
/// <Binding Source="+" />
|
||||
/// <Binding Path="Num2" />
|
||||
/// <Binding Source="-" />
|
||||
/// <Binding Path="Num3" />
|
||||
/// <Binding Source="*" />
|
||||
/// <Binding Path="Num4" />
|
||||
/// <Binding Source="/" />
|
||||
/// <Binding Path="Num5" />
|
||||
/// </MultiBinding>
|
||||
/// //
|
||||
/// <MultiBinding Converter="{StaticResource CalculatorConverter}" ConverterParameter="+-*/">
|
||||
/// <Binding Path="Num1" />
|
||||
/// <Binding Path="Num2" />
|
||||
/// <Binding Path="Num3" />
|
||||
/// <Binding Path="Num4" />
|
||||
/// <Binding Path="Num5" />
|
||||
/// </MultiBinding>
|
||||
/// ]]></code></para>
|
||||
/// </summary>
|
||||
/// <exception cref="Exception">绑定的数量不正确</exception>
|
||||
public class CalculatorConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Any(i => i == DependencyProperty.UnsetValue))
|
||||
return 0.0;
|
||||
if (values.Length == 1)
|
||||
return values[0];
|
||||
double result = System.Convert.ToDouble(values[0]);
|
||||
if (parameter is string operators)
|
||||
{
|
||||
if (operators.Length != values.Length - 1)
|
||||
throw new Exception("Parameter error: operator must be one more than parameter");
|
||||
for (int i = 1; i < values.Length - 1; i++)
|
||||
result = Operation(result, operators[i - 1], System.Convert.ToDouble(values[i]));
|
||||
result = Operation(result, operators.Last(), System.Convert.ToDouble(values.Last()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (System.Convert.ToBoolean(values.Length & 1) is false)
|
||||
throw new Exception("Parameter error: Incorrect quantity");
|
||||
bool isNumber = false;
|
||||
char currentOperator = '0';
|
||||
for (int i = 1; i < values.Length - 1; i++)
|
||||
{
|
||||
if (isNumber is false)
|
||||
{
|
||||
currentOperator = ((string)values[i])[0];
|
||||
isNumber = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = System.Convert.ToDouble(values[i]);
|
||||
result = Operation(result, currentOperator, value);
|
||||
isNumber = false;
|
||||
}
|
||||
}
|
||||
result = Operation(result, currentOperator, System.Convert.ToDouble(values.Last()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double Operation(double value1, char operatorChar, double value2)
|
||||
{
|
||||
return operatorChar switch
|
||||
{
|
||||
'+' => value1 + value2,
|
||||
'-' => value1 - value2,
|
||||
'*' => value1 * value2,
|
||||
'/' => value1 / value2,
|
||||
'%' => value1 % value2,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
}
|
||||
|
||||
public object[] ConvertBack(
|
||||
object value,
|
||||
Type[] targetTypes,
|
||||
object parameter,
|
||||
CultureInfo culture
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
28
VPet.Solution/Converters/EqualsConverter.cs
Normal file
28
VPet.Solution/Converters/EqualsConverter.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
public class EqualsConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(
|
||||
object[] values,
|
||||
Type targetType,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
if (values.Length != 2)
|
||||
throw new NotImplementedException("Values length must be 2");
|
||||
return values[0].Equals(values[1]);
|
||||
}
|
||||
|
||||
public object[] ConvertBack(
|
||||
object value,
|
||||
Type[] targetTypes,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
20
VPet.Solution/Converters/FalseToCollapsedConverter.cs
Normal file
20
VPet.Solution/Converters/FalseToCollapsedConverter.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
public class FalseToCollapsedConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return (bool.TryParse(value.ToString(), out var result) && result)
|
||||
? Visibility.Visible
|
||||
: Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value is Visibility visibility && visibility == Visibility.Collapsed;
|
||||
}
|
||||
}
|
20
VPet.Solution/Converters/FalseToHiddenConverter.cs
Normal file
20
VPet.Solution/Converters/FalseToHiddenConverter.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
public class FalseToHiddenConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return (bool.TryParse(value.ToString(), out var result) && result)
|
||||
? Visibility.Visible
|
||||
: Visibility.Hidden;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value is Visibility visibility && visibility == Visibility.Hidden;
|
||||
}
|
||||
}
|
84
VPet.Solution/Converters/MarginConverter.cs
Normal file
84
VPet.Solution/Converters/MarginConverter.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
/// <summary>
|
||||
/// 边距转换器
|
||||
/// <para>示例:
|
||||
/// <code><![CDATA[
|
||||
/// <MultiBinding Converter="{StaticResource MarginConverter}">
|
||||
/// <Binding Path="Left" />
|
||||
/// <Binding Path="Top" />
|
||||
/// <Binding Path="Right" />
|
||||
/// <Binding Path="Bottom" />
|
||||
/// </MultiBinding>
|
||||
/// ]]></code></para>
|
||||
/// </summary>
|
||||
public class MarginConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(
|
||||
object[] values,
|
||||
Type targetType,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
if (values.Length == 0)
|
||||
{
|
||||
return new Thickness();
|
||||
}
|
||||
else if (values.Length == 1)
|
||||
{
|
||||
return new Thickness()
|
||||
{
|
||||
Left = System.Convert.ToDouble(values[0]),
|
||||
Top = default,
|
||||
Right = default,
|
||||
Bottom = default
|
||||
};
|
||||
}
|
||||
else if (values.Length == 2)
|
||||
{
|
||||
return new Thickness()
|
||||
{
|
||||
Left = System.Convert.ToDouble(values[0]),
|
||||
Top = System.Convert.ToDouble(values[1]),
|
||||
Right = default,
|
||||
Bottom = default
|
||||
};
|
||||
}
|
||||
else if (values.Length == 3)
|
||||
{
|
||||
return new Thickness()
|
||||
{
|
||||
Left = System.Convert.ToDouble(values[0]),
|
||||
Top = System.Convert.ToDouble(values[1]),
|
||||
Right = System.Convert.ToDouble(values[2]),
|
||||
Bottom = default
|
||||
};
|
||||
}
|
||||
else if (values.Length == 4)
|
||||
{
|
||||
return new Thickness()
|
||||
{
|
||||
Left = System.Convert.ToDouble(values[0]),
|
||||
Top = System.Convert.ToDouble(values[1]),
|
||||
Right = System.Convert.ToDouble(values[2]),
|
||||
Bottom = System.Convert.ToDouble(values[3])
|
||||
};
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object[] ConvertBack(
|
||||
object value,
|
||||
Type[] targetTypes,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
26
VPet.Solution/Converters/MaxConverter.cs
Normal file
26
VPet.Solution/Converters/MaxConverter.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
public class MaxConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(
|
||||
object[] values,
|
||||
Type targetType,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
return values.Max(i => (double)i);
|
||||
}
|
||||
|
||||
public object[] ConvertBack(
|
||||
object value,
|
||||
Type[] targetTypes,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
22
VPet.Solution/Converters/MediaColorToBrushConverter.cs
Normal file
22
VPet.Solution/Converters/MediaColorToBrushConverter.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
public class MediaColorToBrushConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not Color color)
|
||||
throw new ArgumentException("Not media color", nameof(value));
|
||||
return new SolidColorBrush(color);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not SolidColorBrush brush)
|
||||
throw new ArgumentException("Not SolidColorBrush", nameof(value));
|
||||
return brush.Color;
|
||||
}
|
||||
}
|
28
VPet.Solution/Converters/NotEqualsConverter.cs
Normal file
28
VPet.Solution/Converters/NotEqualsConverter.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
public class NotEqualsConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(
|
||||
object[] values,
|
||||
Type targetType,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
if (values.Length != 2)
|
||||
throw new NotImplementedException("Values length must be 2");
|
||||
return !values[0].Equals(values[1]);
|
||||
}
|
||||
|
||||
public object[] ConvertBack(
|
||||
object value,
|
||||
Type[] targetTypes,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
17
VPet.Solution/Converters/NullToFalseConverter.cs
Normal file
17
VPet.Solution/Converters/NullToFalseConverter.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
public class NullToFalseConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value is not null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
91
VPet.Solution/Converters/RatioMarginConverter.cs
Normal file
91
VPet.Solution/Converters/RatioMarginConverter.cs
Normal file
@ -0,0 +1,91 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
/// <summary>
|
||||
/// 边距转换器
|
||||
/// <para>示例:
|
||||
/// <code><![CDATA[
|
||||
/// <MultiBinding Converter="{StaticResource RatioMarginConverter}">
|
||||
/// <Binding Path="Left" />
|
||||
/// <Binding Path="Top" />
|
||||
/// <Binding Path="Right" />
|
||||
/// <Binding Path="Bottom" />
|
||||
/// </MultiBinding>
|
||||
/// ]]></code></para>
|
||||
/// </summary>
|
||||
public class RatioMarginConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(
|
||||
object[] values,
|
||||
Type targetType,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
if (values.Any(i => i == DependencyProperty.UnsetValue))
|
||||
return new Thickness();
|
||||
if (values.Length == 0)
|
||||
{
|
||||
return new Thickness();
|
||||
}
|
||||
else if (values.Length == 1)
|
||||
{
|
||||
return new Thickness();
|
||||
}
|
||||
var ratio = System.Convert.ToDouble(values[0]);
|
||||
if (values.Length == 2)
|
||||
{
|
||||
return new Thickness()
|
||||
{
|
||||
Left = System.Convert.ToDouble(values[1]) * ratio,
|
||||
Top = default,
|
||||
Right = default,
|
||||
Bottom = default
|
||||
};
|
||||
}
|
||||
else if (values.Length == 3)
|
||||
{
|
||||
return new Thickness()
|
||||
{
|
||||
Left = System.Convert.ToDouble(values[1]) * ratio,
|
||||
Top = System.Convert.ToDouble(values[2]) * ratio,
|
||||
Right = default,
|
||||
Bottom = default
|
||||
};
|
||||
}
|
||||
else if (values.Length == 4)
|
||||
{
|
||||
return new Thickness()
|
||||
{
|
||||
Left = System.Convert.ToDouble(values[1]) * ratio,
|
||||
Top = System.Convert.ToDouble(values[2]) * ratio,
|
||||
Right = System.Convert.ToDouble(values[3]) * ratio,
|
||||
Bottom = default
|
||||
};
|
||||
}
|
||||
else if (values.Length == 5)
|
||||
{
|
||||
return new Thickness()
|
||||
{
|
||||
Left = System.Convert.ToDouble(values[1]) * ratio,
|
||||
Top = System.Convert.ToDouble(values[2]) * ratio,
|
||||
Right = System.Convert.ToDouble(values[3]) * ratio,
|
||||
Bottom = System.Convert.ToDouble(values[4]) * ratio
|
||||
};
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public object[] ConvertBack(
|
||||
object value,
|
||||
Type[] targetTypes,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
51
VPet.Solution/Converters/StringFormatConverter.cs
Normal file
51
VPet.Solution/Converters/StringFormatConverter.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace VPet.House.Converters;
|
||||
|
||||
/// <summary>
|
||||
/// 边距转换器
|
||||
/// <para>示例:
|
||||
/// <code><![CDATA[
|
||||
/// <MultiBinding Converter="{StaticResource MarginConverter}">
|
||||
/// <Binding Path="StringFormat" />
|
||||
/// <Binding Path="Value1" />
|
||||
/// <Binding Path="Value2" />
|
||||
/// </MultiBinding>
|
||||
/// OR
|
||||
/// <MultiBinding Converter="{StaticResource MarginConverter}" ConverterParameter="{}{0}{1}">
|
||||
/// <Binding Path="Value1" />
|
||||
/// <Binding Path="Value2" />
|
||||
/// </MultiBinding>
|
||||
/// ]]></code></para>
|
||||
/// </summary>
|
||||
public class StringFormatConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(
|
||||
object[] values,
|
||||
Type targetType,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
var formatStr = (string)parameter;
|
||||
if (string.IsNullOrWhiteSpace(formatStr))
|
||||
{
|
||||
formatStr = (string)values[0];
|
||||
return string.Format(formatStr, values.Skip(1).ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Format(formatStr, values);
|
||||
}
|
||||
}
|
||||
|
||||
public object[] ConvertBack(
|
||||
object value,
|
||||
Type[] targetTypes,
|
||||
object parameter,
|
||||
System.Globalization.CultureInfo culture
|
||||
)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
<Window x:Class="VPet.Solution.MainWindow" 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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:VPet.Solution"
|
||||
xmlns:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF" mc:Ignorable="d"
|
||||
xmlns:pu="clr-namespace:Panuon.WPF.UI;assembly=Panuon.WPF.UI" Title="{ll:Str 'VPET 问题解决工具'}" Height="450" Width="800">
|
||||
<Grid>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
12
VPet.Solution/NativeStyles.xaml
Normal file
12
VPet.Solution/NativeStyles.xaml
Normal file
@ -0,0 +1,12 @@
|
||||
<ResourceDictionary
|
||||
x:Class="VPet.Solution.NativeStyles"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="/VPet-Simulator.Windows.Interface;component/ResourceStyle.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/Panuon.WPF.UI;component/Control.xaml" />
|
||||
<ResourceDictionary Source="Converters.xaml" />
|
||||
<ResourceDictionary Source="Templates.xaml" />
|
||||
<ResourceDictionary Source="Styles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
11
VPet.Solution/NativeStyles.xaml.cs
Normal file
11
VPet.Solution/NativeStyles.xaml.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace VPet.Solution;
|
||||
|
||||
public partial class NativeStyles : ResourceDictionary
|
||||
{
|
||||
public NativeStyles()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
@ -33,15 +31,14 @@ using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//或应用程序资源字典中找到时使用)
|
||||
//(未在页面中找到资源时使用,
|
||||
//或应用程序资源字典中找到时使用)
|
||||
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//、应用程序或任何主题专用资源字典中找到时使用)
|
||||
//(未在页面中找到资源时使用,
|
||||
//、应用程序或任何主题专用资源字典中找到时使用)
|
||||
)]
|
||||
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
|
72
VPet.Solution/Resources/NativeResources.cs
Normal file
72
VPet.Solution/Resources/NativeResources.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace VPet.House.Resources;
|
||||
|
||||
/// <summary>
|
||||
/// 本地资源
|
||||
/// </summary>
|
||||
internal class NativeResources
|
||||
{
|
||||
#region Resources
|
||||
|
||||
public const string Wall = ResourcePath + "Wall.png";
|
||||
public const string Floor = ResourcePath + "Floor.png";
|
||||
public const string Chair = ResourcePath + "Chair.png";
|
||||
public const string Table = ResourcePath + "Table.png";
|
||||
public const string Bed = ResourcePath + "Bed.png";
|
||||
|
||||
public const string OakPlanks = ResourcePath + "oak_planks.png";
|
||||
public const string Stone = ResourcePath + "stone.png";
|
||||
|
||||
#endregion Resources
|
||||
|
||||
/// <summary>
|
||||
/// 资源基路径
|
||||
/// </summary>
|
||||
public const string ResourcePath = $"{nameof(VPet)}.{nameof(House)}.{nameof(Resources)}.";
|
||||
|
||||
#region Native
|
||||
|
||||
private static readonly Assembly _assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源流
|
||||
/// </summary>
|
||||
/// <param name="resourceName">资源名</param>
|
||||
/// <returns>资源流</returns>
|
||||
public static Stream GetStream(string resourceName) =>
|
||||
_assembly.GetManifestResourceStream(resourceName)!;
|
||||
|
||||
/// <summary>
|
||||
/// 尝试获取资源流
|
||||
/// </summary>
|
||||
/// <param name="resourceName">资源名</param>
|
||||
/// <param name="resourceStream">资源流</param>
|
||||
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
|
||||
public static bool TryGetStream(string resourceName, out Stream resourceStream)
|
||||
{
|
||||
resourceStream = null;
|
||||
if (_assembly.GetManifestResourceStream(resourceName) is not Stream stream)
|
||||
return false;
|
||||
resourceStream = stream;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将流保存至文件
|
||||
/// </summary>
|
||||
/// <param name="resourceName">资源名</param>
|
||||
/// <param name="path">文件路径</param>
|
||||
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
|
||||
public static bool SaveTo(string resourceName, string path)
|
||||
{
|
||||
if (_assembly.GetManifestResourceStream(resourceName) is not Stream stream)
|
||||
return false;
|
||||
using var sr = new StreamReader(stream);
|
||||
using var sw = new StreamWriter(path);
|
||||
sr.BaseStream.CopyTo(sw.BaseStream);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion Native
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 通知属性改变后接口
|
||||
/// </summary>
|
||||
public interface INotifyPropertyChangedX<TSender>
|
||||
{
|
||||
/// <summary>
|
||||
/// 通知属性改变后事件
|
||||
/// </summary>
|
||||
public event PropertyChangedXEventHandler<TSender>? PropertyChangedX;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 通知属性改变前接口
|
||||
/// </summary>
|
||||
public interface INotifyPropertyChangingX<TSender>
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性改变前事件
|
||||
/// </summary>
|
||||
public event PropertyChangingXEventHandler<TSender>? PropertyChangingX;
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 可观察对象
|
||||
/// <para>示例:<code><![CDATA[
|
||||
/// public class ObservableClassExample : ObservableClass<ObservableClassExample>
|
||||
/// {
|
||||
/// int _value = 0;
|
||||
/// public int Value
|
||||
/// {
|
||||
/// get => _value;
|
||||
/// set => SetProperty(ref _value, value);
|
||||
/// }
|
||||
/// }]]></code></para>
|
||||
/// </summary>
|
||||
public abstract class ObservableClass<TObject>
|
||||
: INotifyPropertyChanging,
|
||||
INotifyPropertyChanged,
|
||||
INotifyPropertyChangingX<TObject>,
|
||||
INotifyPropertyChangedX<TObject>
|
||||
where TObject : ObservableClass<TObject>
|
||||
{
|
||||
#region OnPropertyChange
|
||||
/// <summary>
|
||||
/// 设置属性值
|
||||
/// </summary>
|
||||
/// <param name="value">值</param>
|
||||
/// <param name="newValue">新值</param>
|
||||
/// <param name="propertyName">属性名称</param>
|
||||
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected virtual bool SetProperty<TValue>(
|
||||
ref TValue value,
|
||||
TValue newValue,
|
||||
[CallerMemberName] string propertyName = null!
|
||||
)
|
||||
{
|
||||
if (EqualityComparer<TValue>.Default.Equals(value, newValue) is true)
|
||||
return false;
|
||||
var oldValue = value;
|
||||
if (OnPropertyChanging(oldValue, newValue, propertyName))
|
||||
return false;
|
||||
value = newValue;
|
||||
OnPropertyChanged(oldValue, newValue, propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 属性改变前
|
||||
/// </summary>
|
||||
/// <param name="oldValue">旧值</param>
|
||||
/// <param name="newValue">新值</param>
|
||||
/// <param name="propertyName">属性名称</param>
|
||||
/// <returns>取消为 <see langword="true"/> 否则为 <see langword="false"/></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected virtual bool OnPropertyChanging(
|
||||
object? oldValue,
|
||||
object? newValue,
|
||||
[CallerMemberName] string propertyName = null!
|
||||
)
|
||||
{
|
||||
PropertyChanging?.Invoke(this, new(propertyName));
|
||||
if (PropertyChangingX is null)
|
||||
return false;
|
||||
var e = new PropertyChangingXEventArgs(propertyName, oldValue, newValue);
|
||||
PropertyChangingX?.Invoke((TObject)this, e);
|
||||
if (e.Cancel)
|
||||
PropertyChanged?.Invoke(this, new(propertyName));
|
||||
return e.Cancel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 属性改变后
|
||||
/// </summary>
|
||||
/// <param name="oldValue">旧值</param>
|
||||
/// <param name="newValue">新值</param>
|
||||
/// <param name="propertyName">属性名称</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected virtual void OnPropertyChanged(
|
||||
object? oldValue,
|
||||
object? newValue,
|
||||
[CallerMemberName] string propertyName = null!
|
||||
)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new(propertyName));
|
||||
PropertyChangedX?.Invoke((TObject)this, new(propertyName, oldValue, newValue));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Event
|
||||
/// <inheritdoc/>
|
||||
public event PropertyChangingEventHandler? PropertyChanging;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event PropertyChangingXEventHandler<TObject>? PropertyChangingX;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event PropertyChangedXEventHandler<TObject>? PropertyChangedX;
|
||||
#endregion
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 属性改变后事件参数
|
||||
/// </summary>
|
||||
public class PropertyChangedXEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性名
|
||||
/// </summary>
|
||||
public string PropertyName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 旧值
|
||||
/// </summary>
|
||||
public object? OldValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 新值
|
||||
/// </summary>
|
||||
public object? NewValue { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <param name="propertyName">属性名</param>
|
||||
/// <param name="oldValue">旧值</param>
|
||||
/// <param name="newValue">新值</param>
|
||||
public PropertyChangedXEventArgs(string propertyName, object? oldValue, object? newValue)
|
||||
{
|
||||
PropertyName = propertyName;
|
||||
OldValue = oldValue;
|
||||
NewValue = newValue;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 属性改变后事件
|
||||
/// </summary>
|
||||
/// <param name="sender">发送者</param>
|
||||
/// <param name="e">参数</param>
|
||||
public delegate void PropertyChangedXEventHandler<TSender>(
|
||||
TSender sender,
|
||||
PropertyChangedXEventArgs e
|
||||
);
|
@ -0,0 +1,35 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 属性改变前事件参数
|
||||
/// </summary>
|
||||
public class PropertyChangingXEventArgs : CancelEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性名
|
||||
/// </summary>
|
||||
public string PropertyName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 旧值
|
||||
/// </summary>
|
||||
public object? OldValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 新值
|
||||
/// </summary>
|
||||
public object? NewValue { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <param name="propertyName">属性名</param>
|
||||
/// <param name="oldValue">旧值</param>
|
||||
/// <param name="newValue">新值</param>
|
||||
public PropertyChangingXEventArgs(string propertyName, object? oldValue, object? newValue)
|
||||
{
|
||||
PropertyName = propertyName;
|
||||
OldValue = oldValue;
|
||||
NewValue = newValue;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 属性改变前事件
|
||||
/// </summary>
|
||||
/// <param name="sender">发送者</param>
|
||||
/// <param name="e">参数</param>
|
||||
public delegate void PropertyChangingXEventHandler<TSender>(
|
||||
TSender sender,
|
||||
PropertyChangingXEventArgs e
|
||||
);
|
@ -0,0 +1,12 @@
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 异步执行命令事件
|
||||
/// </summary>
|
||||
public delegate Task ExecuteAsyncEventHandler();
|
||||
|
||||
/// <summary>
|
||||
/// 异步执行命令事件
|
||||
/// </summary>
|
||||
/// <param name="parameter">值</param>
|
||||
public delegate Task ExecuteAsyncEventHandler<T>(T parameter);
|
@ -0,0 +1,12 @@
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 执行事件
|
||||
/// </summary>
|
||||
public delegate void ExecuteEventHandler();
|
||||
|
||||
/// <summary>
|
||||
/// 执行事件
|
||||
/// </summary>
|
||||
/// <param name="parameter">参数</param>
|
||||
public delegate void ExecuteEventHandler<T>(T parameter);
|
@ -0,0 +1,11 @@
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 通知接收器
|
||||
/// </summary>
|
||||
/// <param name="sender">发送者</param>
|
||||
/// <param name="e">参数</param>
|
||||
public delegate void NotifyReceivedEventHandler(ICommand sender, CancelEventArgs e);
|
@ -0,0 +1,115 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 可观察命令
|
||||
/// </summary>
|
||||
[DebuggerDisplay("\\{ObservableCommand, CanExecute = {IsCanExecute.Value}\\}")]
|
||||
public class ObservableCommand : ObservableClass<ObservableCommand>, ICommand
|
||||
{
|
||||
bool _isCanExecute = true;
|
||||
|
||||
/// <summary>
|
||||
/// 能执行的属性
|
||||
/// </summary>
|
||||
public bool IsCanExecute
|
||||
{
|
||||
get => _isCanExecute;
|
||||
set => SetProperty(ref _isCanExecute, value);
|
||||
}
|
||||
|
||||
bool _currentCanExecute = true;
|
||||
|
||||
/// <summary>
|
||||
/// 当前可执行状态
|
||||
/// <para>
|
||||
/// 在执行异步事件时会强制为 <see langword="false"/>, 但异步结束后会恢复为 <see cref="IsCanExecute"/> 的值
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public bool CurrentCanExecute
|
||||
{
|
||||
get => _currentCanExecute;
|
||||
private set => SetProperty(ref _currentCanExecute, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ObservableCommand()
|
||||
{
|
||||
PropertyChanged += OnCanExecuteChanged;
|
||||
}
|
||||
|
||||
private void OnCanExecuteChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, new());
|
||||
}
|
||||
|
||||
#region ICommand
|
||||
/// <summary>
|
||||
/// 能否被执行
|
||||
/// </summary>
|
||||
/// <param name="parameter">参数</param>
|
||||
/// <returns>能被执行为 <see langword="true"/> 否则为 <see langword="false"/></returns>
|
||||
public bool CanExecute(object? parameter)
|
||||
{
|
||||
return CurrentCanExecute && IsCanExecute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行方法
|
||||
/// </summary>
|
||||
/// <param name="parameter">参数</param>
|
||||
public async void Execute(object? parameter)
|
||||
{
|
||||
if (IsCanExecute is not true)
|
||||
return;
|
||||
ExecuteCommand?.Invoke();
|
||||
await ExecuteAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步方法, 会在等待中修改 <see cref="CurrentCanExecute"/>, 完成后恢复
|
||||
/// <para>
|
||||
/// 若要在执行此方法时触发 <see cref="ExecuteCommand"/> 事件, 请将 <paramref name="runAlone"/> 设置为 <see langword="true"/>
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="runAlone">设置为 <see langword="true"/> 时触发 <see cref="ExecuteCommand"/> 事件</param>
|
||||
/// <returns>任务</returns>
|
||||
public async Task ExecuteAsync(bool runAlone = false)
|
||||
{
|
||||
if (IsCanExecute is not true)
|
||||
return;
|
||||
if (runAlone)
|
||||
ExecuteCommand?.Invoke();
|
||||
if (ExecuteAsyncCommand is null)
|
||||
return;
|
||||
CurrentCanExecute = false;
|
||||
foreach (
|
||||
var asyncEvent in ExecuteAsyncCommand
|
||||
.GetInvocationList()
|
||||
.Cast<ExecuteAsyncEventHandler>()
|
||||
)
|
||||
await asyncEvent.Invoke();
|
||||
CurrentCanExecute = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Event
|
||||
/// <summary>
|
||||
/// 能否执行属性改变后事件
|
||||
/// </summary>
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 执行事件
|
||||
/// </summary>
|
||||
public event ExecuteEventHandler? ExecuteCommand;
|
||||
|
||||
/// <summary>
|
||||
/// 异步执行事件
|
||||
/// </summary>
|
||||
public event ExecuteAsyncEventHandler? ExecuteAsyncCommand;
|
||||
#endregion
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HKW.HKWUtils.Observable;
|
||||
|
||||
/// <summary>
|
||||
/// 具有参数的可观察命令
|
||||
/// </summary>
|
||||
[DebuggerDisplay("\\{ObservableCommand, CanExecute = {IsCanExecute.Value}\\}")]
|
||||
public class ObservableCommand<T> : ObservableClass<ObservableCommand>, ICommand
|
||||
{
|
||||
bool _isCanExecute = true;
|
||||
|
||||
/// <summary>
|
||||
/// 能执行的属性
|
||||
/// </summary>
|
||||
public bool IsCanExecute
|
||||
{
|
||||
get => _isCanExecute;
|
||||
set => SetProperty(ref _isCanExecute, value);
|
||||
}
|
||||
|
||||
bool _currentCanExecute = true;
|
||||
|
||||
/// <summary>
|
||||
/// 当前可执行状态
|
||||
/// <para>
|
||||
/// 在执行异步事件时会强制为 <see langword="false"/>, 但异步结束后会恢复为 <see cref="IsCanExecute"/> 的值
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public bool CurrentCanExecute
|
||||
{
|
||||
get => _currentCanExecute;
|
||||
private set => SetProperty(ref _currentCanExecute, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ObservableCommand()
|
||||
{
|
||||
PropertyChanged += OnCanExecuteChanged;
|
||||
}
|
||||
|
||||
private void OnCanExecuteChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, new());
|
||||
}
|
||||
|
||||
#region ICommand
|
||||
/// <summary>
|
||||
/// 能否被执行
|
||||
/// </summary>
|
||||
/// <param name="parameter">参数</param>
|
||||
/// <returns>能被执行为 <see langword="true"/> 否则为 <see langword="false"/></returns>
|
||||
public bool CanExecute(object? parameter)
|
||||
{
|
||||
return CurrentCanExecute && IsCanExecute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行方法
|
||||
/// </summary>
|
||||
/// <param name="parameter">参数</param>
|
||||
public async void Execute(object? parameter)
|
||||
{
|
||||
if (IsCanExecute is not true)
|
||||
return;
|
||||
ExecuteCommand?.Invoke((T)parameter!);
|
||||
await ExecuteAsync((T)parameter!);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行异步方法, 会在等待中修改 <see cref="CurrentCanExecute"/>, 完成后恢复
|
||||
/// <para>
|
||||
/// 若要在执行此方法时触发 <see cref="ExecuteCommand"/> 事件, 请将 <paramref name="runAlone"/> 设置为 <see langword="true"/>
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="parameter">参数</param>
|
||||
/// <param name="runAlone">设置为 <see langword="true"/> 时触发 <see cref="ExecuteCommand"/> 事件</param>
|
||||
/// <returns>任务</returns>
|
||||
public async Task ExecuteAsync(T parameter, bool runAlone = false)
|
||||
{
|
||||
if (IsCanExecute is not true)
|
||||
return;
|
||||
if (runAlone)
|
||||
ExecuteCommand?.Invoke(parameter);
|
||||
if (ExecuteAsyncCommand is null)
|
||||
return;
|
||||
CurrentCanExecute = false;
|
||||
foreach (
|
||||
var asyncEvent in ExecuteAsyncCommand
|
||||
.GetInvocationList()
|
||||
.Cast<ExecuteAsyncEventHandler<T>>()
|
||||
)
|
||||
await asyncEvent.Invoke(parameter);
|
||||
CurrentCanExecute = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Event
|
||||
/// <summary>
|
||||
/// 能否执行属性改变后事件
|
||||
/// </summary>
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 执行事件
|
||||
/// </summary>
|
||||
public event ExecuteEventHandler<T>? ExecuteCommand;
|
||||
|
||||
/// <summary>
|
||||
/// 异步执行事件
|
||||
/// </summary>
|
||||
public event ExecuteAsyncEventHandler<T>? ExecuteAsyncCommand;
|
||||
#endregion
|
||||
}
|
208
VPet.Solution/Styles.xaml
Normal file
208
VPet.Solution/Styles.xaml
Normal file
@ -0,0 +1,208 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:pu="https://opensource.panuon.com/wpf-ui">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/Panuon.WPF.UI;component/Control.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<Style
|
||||
x:Key="Button_Add"
|
||||
BasedOn="{StaticResource {x:Type Button}}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Background" Value="{StaticResource DARKPrimary}" />
|
||||
<Setter Property="pu:ButtonHelper.ShadowColor" Value="{StaticResource ShadowColor}" />
|
||||
<Setter Property="FontSize" Value="24" />
|
||||
<Setter Property="Padding" Value="10" />
|
||||
<Setter Property="Margin" Value="10" />
|
||||
<Setter Property="pu:ButtonHelper.CornerRadius" Value="24" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="Button_Cancel"
|
||||
BasedOn="{StaticResource ThemedButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Background" Value="{StaticResource PrimaryLight}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource SecondaryText}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="Button_HiddenOnTagNull"
|
||||
BasedOn="{StaticResource ThemedButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Visibility" Value="Hidden" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Mode=Self}}" Value="{x:Null}">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="Button_CollapsedOnTagNull"
|
||||
BasedOn="{StaticResource ThemedButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Mode=Self}}" Value="{x:Null}">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBlock_Wrap"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBlock_BaseStyle"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Margin" Value="10,5,10,5" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBlock_LeftCenter"
|
||||
BasedOn="{StaticResource {x:Type TextBlock}}"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBox_Wrap"
|
||||
BasedOn="{StaticResource {x:Type TextBox}}"
|
||||
TargetType="TextBox">
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Top" />
|
||||
<Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBox_Center"
|
||||
BasedOn="{StaticResource {x:Type TextBox}}"
|
||||
TargetType="TextBox">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="TextBox_LeftCenter"
|
||||
BasedOn="{StaticResource {x:Type TextBox}}"
|
||||
TargetType="TextBox">
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="ToolTip" Value="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" />
|
||||
</Style>
|
||||
<Style x:Key="WindowXStyle" TargetType="pu:WindowX">
|
||||
<Setter Property="pu:WindowXCaption.Background" Value="{DynamicResource DARKPrimary}" />
|
||||
<Setter Property="pu:WindowXCaption.Foreground" Value="{DynamicResource DARKPrimaryText}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="Menu_Style"
|
||||
BasedOn="{StaticResource {x:Static pu:StyleKeys.MenuStyle}}"
|
||||
TargetType="Menu">
|
||||
<Setter Property="Height" Value="NaN" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource DARKPrimaryText}" />
|
||||
<Setter Property="Background" Value="{DynamicResource DARKPrimary}" />
|
||||
<Setter Property="pu:MenuHelper.CornerRadius" Value="4" />
|
||||
|
||||
<Setter Property="pu:DropDownHelper.CornerRadius" Value="4" />
|
||||
<!-- -->
|
||||
<Setter Property="pu:MenuHelper.TopLevelItemsBorderThickness" Value="0" />
|
||||
<Setter Property="pu:MenuHelper.TopLevelItemsPadding" Value="5,0,5,0" />
|
||||
<Setter Property="pu:MenuHelper.TopLevelItemsMargin" Value="0" />
|
||||
<Setter Property="pu:MenuHelper.TopLevelItemsHorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="pu:MenuHelper.TopLevelItemsBackground" Value="{DynamicResource DARKPrimary}" />
|
||||
<Setter Property="pu:MenuHelper.TopLevelItemsForeground" Value="{DynamicResource DARKPrimaryText}" />
|
||||
<!-- -->
|
||||
<Setter Property="pu:MenuHelper.SubmenuItemsBorderThickness" Value="0" />
|
||||
<Setter Property="pu:MenuHelper.SubmenuItemsBorderBrush" Value="{DynamicResource DARKPrimary}" />
|
||||
<Setter Property="pu:MenuHelper.SubmenuItemsWidth" Value="NaN" />
|
||||
<Setter Property="pu:MenuHelper.SubmenuItemsHeight" Value="NaN" />
|
||||
<Setter Property="pu:MenuHelper.SubmenuItemsPadding" Value="5" />
|
||||
<Setter Property="pu:MenuHelper.SubmenuItemsMargin" Value="0" />
|
||||
<!--<Setter Property="pu:MenuHelper.SubmenuItemsCornerRadius" Value="4" />-->
|
||||
<Setter Property="pu:MenuHelper.SubmenuItemsBackground" Value="{DynamicResource DARKPrimary}" />
|
||||
<Setter Property="pu:MenuHelper.SubmenuItemsForeground" Value="{DynamicResource DARKPrimaryText}" />
|
||||
<!--<Setter Property="Width" Value="NaN" />
|
||||
<Setter Property="Height" Value="NaN" />
|
||||
<Setter Property="Padding" Value="5" />
|
||||
<Setter Property="Background" Value="{DynamicResource BackgroundColor}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ForegroundColor}" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource BodyFontSize}" />
|
||||
<Setter Property="pu:MenuItemHelper.HoverBackground" Value="{DynamicResource HoverColor}" />
|
||||
<Setter Property="pu:MenuItemHelper.ClickBackground" Value="{DynamicResource ClickColor}" />
|
||||
<Setter Property="pu:MenuItemHelper.CheckedBackground" Value="{DynamicResource CheckedColor}" />-->
|
||||
</Style>
|
||||
<Style x:Key="Switch_BaseStyle" TargetType="pu:Switch">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="Margin" Value="10,5,10,5" />
|
||||
<Setter Property="Background" Value="{x:Null}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryDark}" />
|
||||
<Setter Property="BoxHeight" Value="20" />
|
||||
<Setter Property="CheckedBackground" Value="{DynamicResource Primary}" />
|
||||
<Setter Property="CheckedBorderBrush" Value="{DynamicResource Primary}" />
|
||||
<Setter Property="CheckedToggleBrush" Value="{DynamicResource DARKPrimaryText}" />
|
||||
<Setter Property="ToggleBrush" Value="{DynamicResource PrimaryDark}" />
|
||||
<Setter Property="ToggleShadowColor" Value="{x:Null}" />
|
||||
<Setter Property="ToggleSize" Value="14" />
|
||||
</Style>
|
||||
<Style x:Key="Label_BaseStyle" TargetType="Label">
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="Margin" Value="10,0,10,0" />
|
||||
<Setter Property="Height" Value="30" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="Background" Value="{x:Null}" />
|
||||
</Style>
|
||||
<Style x:Key="NumberInput_BaseStyle" TargetType="pu:NumberInput">
|
||||
<Setter Property="Height" Value="30" />
|
||||
<Setter Property="Margin" Value="10,5,10,5" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Background" Value="{x:Null}" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource DARKPrimaryDarker}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="Button_BaseStyle"
|
||||
BasedOn="{StaticResource {x:Type Button}}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Margin" Value="10,5,10,5" />
|
||||
<Setter Property="Padding" Value="10,5,10,5" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="pu:ButtonHelper.CornerRadius" Value="4" />
|
||||
<Setter Property="Background" Value="{DynamicResource SecondaryLight}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource SecondaryDark}" />
|
||||
<Setter Property="BorderThickness" Value="2" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="ComboBox_BaseStyle"
|
||||
BasedOn="{StaticResource StandardComboBoxStyle}"
|
||||
TargetType="ComboBox">
|
||||
<Setter Property="Margin" Value="10,5,10,5" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="Expander_BaseStyle"
|
||||
BasedOn="{StaticResource {x:Static pu:StyleKeys.ExpanderStyle}}"
|
||||
TargetType="Expander">
|
||||
<Setter Property="Margin" Value="10" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource SecondaryDark}" />
|
||||
<Setter Property="Background" Value="{DynamicResource DARKPrimaryText}" />
|
||||
<Setter Property="BorderThickness" Value="2" />
|
||||
<Setter Property="pu:ExpanderHelper.CornerRadius" Value="4" />
|
||||
<Setter Property="pu:ExpanderHelper.ToggleArrowPlacement" Value="Right" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="Slider_BaseStyle"
|
||||
BasedOn="{StaticResource StandardSliderStyle}"
|
||||
TargetType="Slider">
|
||||
<Setter Property="IsSnapToTickEnabled" Value="True" />
|
||||
<Setter Property="Margin" Value="10,5,10,5" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
58
VPet.Solution/Templates.xaml
Normal file
58
VPet.Solution/Templates.xaml
Normal file
@ -0,0 +1,58 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF"
|
||||
xmlns:pu="https://opensource.panuon.com/wpf-ui">
|
||||
<ContextMenu x:Key="ContextMenu_DataGridRow" x:Shared="false">
|
||||
<MenuItem
|
||||
Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=Page, Mode=FindAncestor}}"
|
||||
CommandParameter="{Binding DataContext, RelativeSource={RelativeSource AncestorType=DataGridRow, Mode=FindAncestor}}"
|
||||
Header="{ll:Str 修改}" />
|
||||
<MenuItem
|
||||
Command="{Binding DataContext.RemoveCommand, RelativeSource={RelativeSource AncestorType=Page, Mode=FindAncestor}}"
|
||||
CommandParameter="{Binding DataContext, RelativeSource={RelativeSource AncestorType=DataGridRow, Mode=FindAncestor}}"
|
||||
Header="{ll:Str 删除}" />
|
||||
</ContextMenu>
|
||||
<ControlTemplate x:Key="ListBoxItem_RangeData" TargetType="ListBoxItem">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Label HorizontalContentAlignment="Center" Content="{Binding Tag, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" />
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="{ll:Str 最小值}" />
|
||||
<pu:NumberInput
|
||||
Grid.Column="1"
|
||||
ToolTip="{Binding Value, RelativeSource={RelativeSource Mode=Self}}"
|
||||
Value="{Binding DataContext.Min.Value, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" />
|
||||
<Label Grid.Row="1" Content="{ll:Str 最大值}" />
|
||||
<pu:NumberInput
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
ToolTip="{Binding Value, RelativeSource={RelativeSource Mode=Self}}"
|
||||
Value="{Binding DataContext.Max.Value, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="ListBox_ShowLangs" TargetType="ListBox">
|
||||
<ListBox
|
||||
ItemsSource="{Binding I18nData.CultureNames}"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
SelectedItem="{Binding I18nData.CultureName.Value}">
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem">
|
||||
<Setter Property="Content" Value="{Binding}" />
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
</ListBox>
|
||||
</ControlTemplate>
|
||||
</ResourceDictionary>
|
7
VPet.Solution/Usings.cs
Normal file
7
VPet.Solution/Usings.cs
Normal file
@ -0,0 +1,7 @@
|
||||
global using global::HKW.HKWUtils;
|
||||
global using global::HKW.HKWUtils.Observable;
|
||||
global using global::System;
|
||||
global using global::System.Collections.Generic;
|
||||
global using global::System.IO;
|
||||
global using global::System.Linq;
|
||||
global using global::System.Threading.Tasks;
|
21
VPet.Solution/Utils/ClearFocus.cs
Normal file
21
VPet.Solution/Utils/ClearFocus.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HKW.WPF.Extensions;
|
||||
|
||||
public static partial class WPFExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 清除元素焦点
|
||||
/// </summary>
|
||||
/// <param name="obj">元素</param>
|
||||
public static void ClearFocus(this DependencyObject obj)
|
||||
{
|
||||
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(obj), null);
|
||||
}
|
||||
}
|
271
VPet.Solution/Utils/ElementHelper.cs
Normal file
271
VPet.Solution/Utils/ElementHelper.cs
Normal file
@ -0,0 +1,271 @@
|
||||
using HKW.WPF.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HKW.WPF.Helpers;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class ElementHelper
|
||||
{
|
||||
#region IsEnabled
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetIsEnabled(FrameworkElement element)
|
||||
{
|
||||
return (bool)element.GetValue(IsEnabledProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static void SetIsEnabled(FrameworkElement element, bool value)
|
||||
{
|
||||
element.SetValue(IsEnabledProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在按下指定按键时清除选中状态
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsEnabledProperty =
|
||||
DependencyProperty.RegisterAttached(
|
||||
"IsEnabled",
|
||||
typeof(bool),
|
||||
typeof(ElementHelper),
|
||||
new FrameworkPropertyMetadata(default(bool), IsEnabledPropertyChangedCallback)
|
||||
);
|
||||
|
||||
private static void IsEnabledPropertyChangedCallback(
|
||||
DependencyObject obj,
|
||||
DependencyPropertyChangedEventArgs e
|
||||
)
|
||||
{
|
||||
if (obj is not FrameworkElement element)
|
||||
return;
|
||||
element.IsEnabled = GetIsEnabled(element);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ClearFocusOnKeyDown
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetClearFocusOnKeyDown(FrameworkElement element)
|
||||
{
|
||||
return (string)element.GetValue(ClearFocusOnKeyDownProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <exception cref="Exception">禁止使用此方法</exception>
|
||||
public static void SetClearFocusOnKeyDown(FrameworkElement element, string value)
|
||||
{
|
||||
element.SetValue(ClearFocusOnKeyDownProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在按下指定按键时清除选中状态
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ClearFocusOnKeyDownProperty =
|
||||
DependencyProperty.RegisterAttached(
|
||||
"ClearFocusOnKeyDown",
|
||||
typeof(string),
|
||||
typeof(ElementHelper),
|
||||
new FrameworkPropertyMetadata(default(string), ClearFocusOnKeyDownPropertyChanged)
|
||||
);
|
||||
|
||||
private static void ClearFocusOnKeyDownPropertyChanged(
|
||||
DependencyObject obj,
|
||||
DependencyPropertyChangedEventArgs e
|
||||
)
|
||||
{
|
||||
if (obj is not FrameworkElement element)
|
||||
return;
|
||||
var keyName = GetClearFocusOnKeyDown(element);
|
||||
if (Enum.TryParse<Key>(keyName, false, out _) is false)
|
||||
throw new Exception($"Unknown key {keyName}");
|
||||
element.KeyDown -= Element_KeyDown;
|
||||
element.KeyDown += Element_KeyDown;
|
||||
|
||||
static void Element_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (sender is not FrameworkElement element)
|
||||
return;
|
||||
var key = (Key)Enum.Parse(typeof(Key), GetClearFocusOnKeyDown(element));
|
||||
if (e.Key == key)
|
||||
{
|
||||
// 清除控件焦点
|
||||
element.ClearFocus();
|
||||
// 清除键盘焦点
|
||||
Keyboard.ClearFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UniformMinWidthGroup
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetUniformMinWidthGroup(FrameworkElement element)
|
||||
{
|
||||
return (string)element.GetValue(UniformWidthGroupProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static void SetUniformMinWidthGroup(FrameworkElement element, string value)
|
||||
{
|
||||
element.SetValue(UniformWidthGroupProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty UniformWidthGroupProperty =
|
||||
DependencyProperty.RegisterAttached(
|
||||
"UniformMinWidthGroup",
|
||||
typeof(string),
|
||||
typeof(ElementHelper),
|
||||
new FrameworkPropertyMetadata(null, UniformMinWidthGroupPropertyChanged)
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// (TopParent ,(GroupName, UniformMinWidthGroupInfo))
|
||||
/// </summary>
|
||||
private readonly static Dictionary<
|
||||
FrameworkElement,
|
||||
Dictionary<string, UniformMinWidthGroupInfo>
|
||||
> _uniformMinWidthGroups = new();
|
||||
|
||||
private static void UniformMinWidthGroupPropertyChanged(
|
||||
DependencyObject obj,
|
||||
DependencyPropertyChangedEventArgs e
|
||||
)
|
||||
{
|
||||
if (obj is not FrameworkElement element)
|
||||
return;
|
||||
var groupName = GetUniformMinWidthGroup(element);
|
||||
var topParent = element.FindTopParentOnVisualTree();
|
||||
// 在设计器中会无法获取顶级元素, 会提示错误, 忽略即可
|
||||
if (topParent is null)
|
||||
return;
|
||||
if (_uniformMinWidthGroups.TryGetValue(topParent, out var groups) is false)
|
||||
{
|
||||
topParent.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
|
||||
groups = _uniformMinWidthGroups[topParent] = new();
|
||||
}
|
||||
if (groups.TryGetValue(groupName, out var group) is false)
|
||||
group = groups[groupName] = new();
|
||||
group.Elements.Add(element);
|
||||
|
||||
element.SizeChanged -= Element_SizeChanged;
|
||||
element.SizeChanged += Element_SizeChanged;
|
||||
|
||||
#region TopParent
|
||||
|
||||
static void Dispatcher_ShutdownStarted(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is not FrameworkElement element)
|
||||
return;
|
||||
_uniformMinWidthGroups.Remove(element);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Element
|
||||
static void Element_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (sender is not FrameworkElement element)
|
||||
return;
|
||||
var groupName = GetUniformMinWidthGroup(element);
|
||||
var topParent = element.FindTopParentOnVisualTree();
|
||||
var groups = _uniformMinWidthGroups[topParent];
|
||||
var group = groups[groupName];
|
||||
var maxWidthElement = group.Elements.MaxBy(i => i.ActualWidth);
|
||||
if (maxWidthElement is null)
|
||||
return;
|
||||
|
||||
if (maxWidthElement.ActualWidth == element.ActualWidth)
|
||||
maxWidthElement = element;
|
||||
if (maxWidthElement.ActualWidth > group.MaxWidth)
|
||||
{
|
||||
// 如果当前控件最大宽度的超过历史最大宽度, 表明非最大宽度列表中的控件超过了历史最大宽度
|
||||
foreach (var item in group.Elements)
|
||||
item.MinWidth = maxWidthElement.ActualWidth;
|
||||
// 将当前控件最小宽度设为0
|
||||
maxWidthElement.MinWidth = 0;
|
||||
group.MaxWidthElements.Clear();
|
||||
// 设为最大宽度的唯一控件
|
||||
group.MaxWidthElements.Add(maxWidthElement);
|
||||
group.MaxWidth = maxWidthElement.ActualWidth;
|
||||
}
|
||||
else if (group.MaxWidthElements.Count == 1)
|
||||
{
|
||||
maxWidthElement = group.MaxWidthElements.First();
|
||||
// 当最大宽度控件只有一个时, 并且当前控件宽度小于历史最大宽度时, 表明需要降低全体宽度
|
||||
if (group.MaxWidth > maxWidthElement.ActualWidth)
|
||||
{
|
||||
// 最小宽度设为0以自适应宽度
|
||||
foreach (var item in group.Elements)
|
||||
item.MinWidth = 0;
|
||||
// 清空最大宽度列表, 让其刷新
|
||||
group.MaxWidthElements.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 将 MaxWidth 设置为 double.MaxValue 时, 可以让首次加载时进入此处
|
||||
foreach (var item in group.Elements)
|
||||
{
|
||||
// 当控件最小宽度为0(表示其为主导宽度的控件), 并且其宽度等于最大宽度, 加入最大宽度列表
|
||||
if (item.MinWidth == 0 && item.ActualWidth == maxWidthElement.ActualWidth)
|
||||
{
|
||||
group.MaxWidthElements.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果不是, 则从最大宽度列表删除, 并设置最小宽度为当前最大宽度
|
||||
group.MaxWidthElements.Remove(item);
|
||||
item.MinWidth = maxWidthElement.ActualWidth;
|
||||
}
|
||||
}
|
||||
group.MaxWidth = maxWidthElement.ActualWidth;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 统一最小宽度分组信息
|
||||
/// </summary>
|
||||
public class UniformMinWidthGroupInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 最后一个最大宽度
|
||||
/// </summary>
|
||||
public double MaxWidth { get; set; } = double.MaxValue;
|
||||
|
||||
/// <summary>
|
||||
/// 所有控件
|
||||
/// </summary>
|
||||
public HashSet<FrameworkElement> Elements { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 最大宽度的控件
|
||||
/// </summary>
|
||||
public HashSet<FrameworkElement> MaxWidthElements { get; } = new();
|
||||
}
|
357
VPet.Solution/Utils/Expansions.cs
Normal file
357
VPet.Solution/Utils/Expansions.cs
Normal file
@ -0,0 +1,357 @@
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace HKW.HKWUtils;
|
||||
|
||||
/// <summary>
|
||||
/// 拓展
|
||||
/// </summary>
|
||||
public static class Extensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="comparisonType"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Contains(this string source, string value, StringComparison comparisonType)
|
||||
{
|
||||
return source.IndexOf(value, comparisonType) >= 0;
|
||||
}
|
||||
|
||||
public static TSource MaxBy<TSource, TKey>(
|
||||
this IEnumerable<TSource> source,
|
||||
Func<TSource, TKey> keySelector
|
||||
)
|
||||
{
|
||||
using IEnumerator<TSource> e = source.GetEnumerator();
|
||||
if (e.MoveNext() is false)
|
||||
return default;
|
||||
TSource value = e.Current;
|
||||
TKey key = keySelector(value);
|
||||
while (e.MoveNext())
|
||||
{
|
||||
TSource nextValue = e.Current;
|
||||
TKey nextKey = keySelector(nextValue);
|
||||
if (Comparer<TKey>.Default.Compare(nextKey, key) > 0)
|
||||
{
|
||||
key = nextKey;
|
||||
value = nextValue;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
//public static string GetSourceFile(this BitmapImage image)
|
||||
//{
|
||||
// return ((FileStream)image.StreamSource).Name;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭流
|
||||
/// </summary>
|
||||
/// <param name="source">图像资源</param>
|
||||
public static void CloseStream(this ImageSource source)
|
||||
{
|
||||
if (source is not BitmapImage image)
|
||||
return;
|
||||
image.StreamSource?.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 图像复制
|
||||
/// </summary>
|
||||
/// <param name="image">图像</param>
|
||||
/// <returns>复制的图像</returns>
|
||||
public static BitmapImage Copy(this BitmapImage image)
|
||||
{
|
||||
if (image is null)
|
||||
return null;
|
||||
BitmapImage newImage = new();
|
||||
newImage.BeginInit();
|
||||
newImage.DecodePixelWidth = image.DecodePixelWidth;
|
||||
newImage.DecodePixelHeight = image.DecodePixelHeight;
|
||||
try
|
||||
{
|
||||
using var bitmap = new Bitmap(image.StreamSource);
|
||||
var ms = new MemoryStream();
|
||||
bitmap.Save(ms, ImageFormat.Png);
|
||||
image.StreamSource.CopyTo(ms);
|
||||
newImage.StreamSource = ms;
|
||||
}
|
||||
finally
|
||||
{
|
||||
newImage.EndInit();
|
||||
}
|
||||
return newImage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存至Png图片
|
||||
/// </summary>
|
||||
/// <param name="image">图片资源</param>
|
||||
/// <param name="path">路径</param>
|
||||
//public static void SaveToPng(this BitmapImage image, string path)
|
||||
//{
|
||||
// if (image is null)
|
||||
// return;
|
||||
// if (path.EndsWith(".png") is false)
|
||||
// path += ".png";
|
||||
// var encoder = new PngBitmapEncoder();
|
||||
// var stream = image.StreamSource;
|
||||
// // 保存位置
|
||||
// var position = stream.Position;
|
||||
// // 必须要重置位置, 否则EndInit将出错
|
||||
// stream.Seek(0, SeekOrigin.Begin);
|
||||
// encoder.Frames.Add(BitmapFrame.Create(image.StreamSource));
|
||||
// // 恢复位置
|
||||
// stream.Seek(position, SeekOrigin.Begin);
|
||||
// using var fs = new FileStream(path, FileMode.Create);
|
||||
// encoder.Save(fs);
|
||||
//}
|
||||
public static void SaveToPng(this BitmapImage image, string path)
|
||||
{
|
||||
if (image is null)
|
||||
return;
|
||||
if (path.EndsWith(".png") is false)
|
||||
path += ".png";
|
||||
var stream = image.StreamSource;
|
||||
// 保存位置
|
||||
var position = stream.Position;
|
||||
// 必须要重置位置, 否则EndInit将出错
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
using var fs = new FileStream(path, FileMode.Create);
|
||||
stream.CopyTo(fs);
|
||||
// 恢复位置
|
||||
stream.Seek(position, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试添加
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">键类型</typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dictionary"></param>
|
||||
/// <param name="key">键</param>
|
||||
/// <param name="value">值</param>
|
||||
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
|
||||
public static bool TryAdd<TKey, TValue>(
|
||||
this IDictionary<TKey, TValue> dictionary,
|
||||
TKey key,
|
||||
TValue value
|
||||
)
|
||||
{
|
||||
if (dictionary.ContainsKey(key))
|
||||
return false;
|
||||
dictionary.Add(key, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 流内容对比
|
||||
/// </summary>
|
||||
/// <param name="source">原始流</param>
|
||||
/// <param name="target">目标流</param>
|
||||
/// <param name="bufferLength">缓冲区大小 (越大速度越快(流内容越大效果越明显), 但会提高内存占用 (bufferSize = bufferLength * sizeof(long) * 2))</param>
|
||||
/// <returns>内容相同为 <see langword="true"/> 否则为 <see langword="false"/></returns>
|
||||
public static bool ContentsEqual(this Stream source, Stream target, int bufferLength = 8)
|
||||
{
|
||||
int bufferSize = bufferLength * sizeof(long);
|
||||
var sourceBuffer = new byte[bufferSize];
|
||||
var targetBuffer = new byte[bufferSize];
|
||||
while (true)
|
||||
{
|
||||
int sourceCount = ReadFullBuffer(source, sourceBuffer);
|
||||
int targetCount = ReadFullBuffer(target, targetBuffer);
|
||||
if (sourceCount != targetCount)
|
||||
return false;
|
||||
if (sourceCount == 0)
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < sourceCount; i += sizeof(long))
|
||||
if (BitConverter.ToInt64(sourceBuffer, i) != BitConverter.ToInt64(targetBuffer, i))
|
||||
return false;
|
||||
}
|
||||
static int ReadFullBuffer(Stream stream, byte[] buffer)
|
||||
{
|
||||
int bytesRead = 0;
|
||||
while (bytesRead < buffer.Length)
|
||||
{
|
||||
int read = stream.Read(buffer, bytesRead, buffer.Length - bytesRead);
|
||||
if (read == 0)
|
||||
return bytesRead;
|
||||
bytesRead += read;
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
public static T? FindVisualChild<T>(this DependencyObject obj)
|
||||
where T : DependencyObject
|
||||
{
|
||||
if (obj is null)
|
||||
return null;
|
||||
var count = VisualTreeHelper.GetChildrenCount(obj);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(obj, i);
|
||||
if (child is T t)
|
||||
return t;
|
||||
if (FindVisualChild<T>(child) is T childItem)
|
||||
return childItem;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static T FindParent<T>(this DependencyObject obj)
|
||||
where T : class
|
||||
{
|
||||
while (obj != null)
|
||||
{
|
||||
if (obj is T)
|
||||
return obj as T;
|
||||
obj = VisualTreeHelper.GetParent(obj);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetFullInfo(this CultureInfo cultureInfo)
|
||||
{
|
||||
return $"{cultureInfo.DisplayName} [{cultureInfo.Name}]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试使用索引获取值
|
||||
/// </summary>
|
||||
/// <typeparam name="T">值类型</typeparam>
|
||||
/// <param name="list">列表</param>
|
||||
/// <param name="index">索引</param>
|
||||
/// <param name="value">值</param>
|
||||
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
|
||||
public static bool TryGetValue<T>(this IList<T> list, int index, out T value)
|
||||
{
|
||||
value = default;
|
||||
if (index < 0 || index >= list.Count)
|
||||
return false;
|
||||
value = list[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试使用索引获取值
|
||||
/// </summary>
|
||||
/// <typeparam name="T">值类型</typeparam>
|
||||
/// <param name="list">列表</param>
|
||||
/// <param name="index">索引</param>
|
||||
/// <param name="value">值</param>
|
||||
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
|
||||
public static bool TryGetValue<T>(this IList list, int index, out object value)
|
||||
{
|
||||
value = default;
|
||||
if (index < 0 || index >= list.Count)
|
||||
return false;
|
||||
value = list[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="weakReference">弱引用</param>
|
||||
/// <returns>获取成功返回目标值, 获取失败则返回 <see langword="null"/></returns>
|
||||
public static T? GetTarget<T>(this WeakReference<T> weakReference)
|
||||
where T : class
|
||||
{
|
||||
return weakReference.TryGetTarget(out var t) ? t : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 枚举出带有索引值的枚举值
|
||||
/// </summary>
|
||||
/// <typeparam name="T">值类型</typeparam>
|
||||
/// <param name="collection">集合</param>
|
||||
/// <returns>带有索引的枚举值</returns>
|
||||
public static IEnumerable<ItemInfo<T>> Enumerate<T>(this IEnumerable<T> collection)
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var item in collection)
|
||||
yield return new(index++, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置视图模型
|
||||
/// </summary>
|
||||
/// <typeparam name="T">视图模型类型</typeparam>
|
||||
/// <param name="window">窗口</param>
|
||||
public static Lazy<T> SetViewModel<T>(this Window window, EventHandler? closedEvent = null)
|
||||
where T : new()
|
||||
{
|
||||
if (window.DataContext is null)
|
||||
{
|
||||
window.DataContext = new T();
|
||||
window.Closed += (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
window.DataContext = null;
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
window.Closed += closedEvent;
|
||||
}
|
||||
return new(() => (T)window.DataContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置视图模型
|
||||
/// </summary>
|
||||
/// <typeparam name="T">视图模型类型</typeparam>
|
||||
/// <param name="page">页面</param>
|
||||
public static Lazy<T> SetViewModel<T>(this Page page)
|
||||
where T : new()
|
||||
{
|
||||
return new(() => (T)(page.DataContext ??= new T()));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 项信息
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
[DebuggerDisplay("[{Index}, {Value}]")]
|
||||
public readonly struct ItemInfo<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 索引值
|
||||
/// </summary>
|
||||
public int Index { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public T Value { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <param name="value">值</param>
|
||||
/// <param name="index">索引值</param>
|
||||
public ItemInfo(int index, T value)
|
||||
{
|
||||
Index = index;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{Index}, {Value}]";
|
||||
}
|
||||
}
|
118
VPet.Solution/Utils/FindTopParent.cs
Normal file
118
VPet.Solution/Utils/FindTopParent.cs
Normal file
@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace HKW.WPF.Extensions;
|
||||
|
||||
public static partial class WPFExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 判断是否是顶级元素, 它必须是 <see cref="Window"/>, <see cref="Page"/>, <see cref="UserControl"/> 中的一个
|
||||
/// </summary>
|
||||
/// <param name="element">元素</param>
|
||||
public static bool IsTopParent(this FrameworkElement element)
|
||||
{
|
||||
if (element is Window || element is Page || element is UserControl)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 寻找它的顶级元素, 它肯定是 <see cref="Window"/>, <see cref="Page"/>, <see cref="UserControl"/> 中的一个
|
||||
/// </summary>
|
||||
/// <param name="element">元素</param>
|
||||
public static FrameworkElement FindTopParent(this FrameworkElement element)
|
||||
{
|
||||
if (element.IsTopParent())
|
||||
return element;
|
||||
var parent = element.Parent as FrameworkElement;
|
||||
while (parent is not null)
|
||||
{
|
||||
if (parent.IsTopParent())
|
||||
return parent;
|
||||
parent = parent.Parent as FrameworkElement;
|
||||
}
|
||||
return null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试寻找它的顶级元素, 它肯定是 <see cref="Window"/>, <see cref="Page"/>, <see cref="UserControl"/> 中的一个
|
||||
/// </summary>
|
||||
/// <param name="element">元素</param>
|
||||
/// <param name="topParent">顶级元素</param>
|
||||
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
|
||||
public static bool TryFindTopParent(
|
||||
this FrameworkElement element,
|
||||
out FrameworkElement topParent
|
||||
)
|
||||
{
|
||||
var result = element.FindTopParent();
|
||||
if (result is null)
|
||||
{
|
||||
topParent = null;
|
||||
return false;
|
||||
}
|
||||
topParent = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在视觉树上寻找它的顶级元素, 它肯定是 <see cref="Window"/>, <see cref="Page"/>, <see cref="UserControl"/> 中的一个
|
||||
/// <para>
|
||||
/// 用于 <see cref="FindTopParent"/> 无法获取到顶级元素的情况下使用, 此元素通常位于 <see cref="DataTemplate"/> 中
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="element">元素</param>
|
||||
public static FrameworkElement FindTopParentOnVisualTree(this FrameworkElement element)
|
||||
{
|
||||
if (element.TryFindTopParent(out var top))
|
||||
return top;
|
||||
var temp = (DependencyObject)element;
|
||||
while ((temp = VisualTreeHelper.GetParent(temp)) is not null)
|
||||
{
|
||||
if (temp is FrameworkElement fe && fe.TryFindTopParent(out var topParent))
|
||||
return topParent;
|
||||
}
|
||||
return null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试在视觉树上寻找它的顶级元素, 它肯定是 <see cref="Window"/>, <see cref="Page"/>, <see cref="UserControl"/> 中的一个
|
||||
/// </summary>
|
||||
/// <param name="element">元素</param>
|
||||
/// <param name="topParent">顶级元素</param>
|
||||
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
|
||||
public static bool FindTopParentOnVisualTree(
|
||||
this FrameworkElement element,
|
||||
out FrameworkElement topParent
|
||||
)
|
||||
{
|
||||
var result = element.FindTopParentOnVisualTree();
|
||||
if (result is null)
|
||||
{
|
||||
topParent = null;
|
||||
return false;
|
||||
}
|
||||
topParent = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 寻找它的顶级元素, 它肯定是 <see cref="Window"/>, <see cref="Page"/>, <see cref="UserControl"/> 中的一个
|
||||
/// </summary>
|
||||
/// <param name="element">元素</param>
|
||||
public static TParent FindTopParent<TParent>(this FrameworkElement element)
|
||||
where TParent : FrameworkElement
|
||||
{
|
||||
var type = typeof(TParent);
|
||||
if (type != typeof(Window) && type != typeof(Page) && type != typeof(UserControl))
|
||||
throw new Exception("TParent type must be Window, Page or UserControl");
|
||||
return (TParent)FindTopParent(element);
|
||||
}
|
||||
}
|
66
VPet.Solution/Utils/HashCode.cs
Normal file
66
VPet.Solution/Utils/HashCode.cs
Normal file
@ -0,0 +1,66 @@
|
||||
namespace HKW.HKWUtils;
|
||||
|
||||
/// <summary>
|
||||
/// 哈希值
|
||||
/// </summary>
|
||||
public class HashCode
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认种子
|
||||
/// </summary>
|
||||
public const int DefaultSeed = 114514;
|
||||
|
||||
/// <summary>
|
||||
/// 默认系数
|
||||
/// </summary>
|
||||
public const int DefaultFactor = 1919810;
|
||||
|
||||
/// <summary>
|
||||
/// 组合哈希值
|
||||
/// </summary>
|
||||
/// <param name="values">值</param>
|
||||
/// <returns>组合的哈希值</returns>
|
||||
public static int Combine(params object[] values)
|
||||
{
|
||||
return CustomHash(DefaultSeed, DefaultFactor, values.Select(v => v.GetHashCode()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 组合哈希值
|
||||
/// </summary>
|
||||
/// <param name="seed">种子</param>
|
||||
/// <param name="factor">系数</param>
|
||||
/// <param name="values">值</param>
|
||||
/// <returns>组合的哈希值</returns>
|
||||
public static int Combine(int seed, int factor, params object[] values)
|
||||
{
|
||||
return CustomHash(seed, factor, values.Select(v => v.GetHashCode()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义组合哈希
|
||||
/// </summary>
|
||||
/// <param name="seed">种子</param>
|
||||
/// <param name="factor">系数</param>
|
||||
/// <param name="collection">哈希集合</param>
|
||||
/// <returns>组合的哈希</returns>
|
||||
public static int CustomHash(int seed, int factor, IEnumerable<int> collection)
|
||||
{
|
||||
int hash = seed;
|
||||
foreach (int i in collection)
|
||||
hash = unchecked((hash * factor) + i);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 自定义组合哈希
|
||||
/// </summary>
|
||||
/// <param name="seed">种子</param>
|
||||
/// <param name="factor">系数</param>
|
||||
/// <param name="values">哈希集合</param>
|
||||
/// <returns>组合的哈希</returns>
|
||||
public static int CustomHash(int seed, int factor, params int[] values)
|
||||
{
|
||||
return CustomHash(seed, factor, collection: values);
|
||||
}
|
||||
}
|
72
VPet.Solution/Utils/ObservableEnumFlags.cs
Normal file
72
VPet.Solution/Utils/ObservableEnumFlags.cs
Normal file
@ -0,0 +1,72 @@
|
||||
namespace HKW.HKWUtils;
|
||||
|
||||
/// <summary>
|
||||
/// 可观察的枚举标签模型
|
||||
/// </summary>
|
||||
/// <typeparam name="T">枚举类型</typeparam>
|
||||
public class ObservableEnumFlags<T> : ObservableClass<ObservableEnumFlags<T>>
|
||||
where T : Enum
|
||||
{
|
||||
private T _EnumValue;
|
||||
public T EnumValue
|
||||
{
|
||||
get => _EnumValue;
|
||||
set => SetProperty(ref _EnumValue, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加枚举命令
|
||||
/// </summary>
|
||||
public ObservableCommand<T> AddCommand { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 删除枚举命令
|
||||
/// </summary>
|
||||
public ObservableCommand<T> RemoveCommand { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 枚举类型
|
||||
/// </summary>
|
||||
public Type EnumType = typeof(T);
|
||||
|
||||
/// <summary>
|
||||
/// 枚举基类
|
||||
/// </summary>
|
||||
public Type UnderlyingType { get; } = Enum.GetUnderlyingType(typeof(T));
|
||||
|
||||
public ObservableEnumFlags()
|
||||
{
|
||||
if (Attribute.IsDefined(EnumType, typeof(FlagsAttribute)) is false)
|
||||
throw new Exception($"此枚举类型未使用特性 [{nameof(FlagsAttribute)}]");
|
||||
AddCommand.ExecuteCommand += AddCommand_Execute;
|
||||
RemoveCommand.ExecuteCommand += RemoveCommand_Execute;
|
||||
}
|
||||
|
||||
public ObservableEnumFlags(T value)
|
||||
: this()
|
||||
{
|
||||
EnumValue = value;
|
||||
}
|
||||
|
||||
private void AddCommand_Execute(T v)
|
||||
{
|
||||
if (UnderlyingType == typeof(int))
|
||||
{
|
||||
EnumValue = (T)
|
||||
Enum.Parse(EnumType, (Convert.ToInt32(EnumValue) | Convert.ToInt32(v)).ToString());
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException($"Value type: {UnderlyingType}");
|
||||
}
|
||||
|
||||
private void RemoveCommand_Execute(T v)
|
||||
{
|
||||
if (UnderlyingType == typeof(int))
|
||||
{
|
||||
EnumValue = (T)
|
||||
Enum.Parse(EnumType, (Convert.ToInt32(EnumValue) & ~Convert.ToInt32(v)).ToString());
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException($"Value type: {UnderlyingType}");
|
||||
}
|
||||
}
|
77
VPet.Solution/Utils/ObservablePoint.cs
Normal file
77
VPet.Solution/Utils/ObservablePoint.cs
Normal file
@ -0,0 +1,77 @@
|
||||
namespace HKW.HKWUtils;
|
||||
|
||||
/// <summary>
|
||||
/// 可观察地点
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
public class ObservablePoint<T>
|
||||
: ObservableClass<ObservablePoint<T>>,
|
||||
IEquatable<ObservablePoint<T>>
|
||||
{
|
||||
private T _x;
|
||||
public T X
|
||||
{
|
||||
get => _x;
|
||||
set => SetProperty(ref _x, value);
|
||||
}
|
||||
|
||||
private T _y;
|
||||
public T Y
|
||||
{
|
||||
get => _y;
|
||||
set => SetProperty(ref _y, value);
|
||||
}
|
||||
|
||||
public ObservablePoint() { }
|
||||
|
||||
public ObservablePoint(T x, T y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制一个新的对象
|
||||
/// </summary>
|
||||
/// <returns>新对象</returns>
|
||||
public ObservablePoint<T> Copy()
|
||||
{
|
||||
return new(X, Y);
|
||||
}
|
||||
|
||||
#region Other
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(X, Y);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is ObservablePoint<T> temp
|
||||
&& EqualityComparer<T>.Default.Equals(X, temp.X)
|
||||
&& EqualityComparer<T>.Default.Equals(Y, temp.Y);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(ObservablePoint<T>? other)
|
||||
{
|
||||
return Equals(obj: other);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator ==(ObservablePoint<T> a, ObservablePoint<T> b)
|
||||
{
|
||||
return Equals(a, b);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator !=(ObservablePoint<T> a, ObservablePoint<T> b)
|
||||
{
|
||||
return Equals(a, b) is not true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
77
VPet.Solution/Utils/ObservableRange.cs
Normal file
77
VPet.Solution/Utils/ObservableRange.cs
Normal file
@ -0,0 +1,77 @@
|
||||
namespace HKW.HKWUtils;
|
||||
|
||||
/// <summary>
|
||||
/// 可观察的范围
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
public class ObservableRange<T>
|
||||
: ObservableClass<ObservableRange<T>>,
|
||||
IEquatable<ObservableRange<T>>
|
||||
{
|
||||
private T _min;
|
||||
public T Min
|
||||
{
|
||||
get => _min;
|
||||
set => SetProperty(ref _min, value);
|
||||
}
|
||||
|
||||
private T _max;
|
||||
public T Max
|
||||
{
|
||||
get => _max;
|
||||
set => SetProperty(ref _max, value);
|
||||
}
|
||||
|
||||
public ObservableRange() { }
|
||||
|
||||
public ObservableRange(T min, T max)
|
||||
{
|
||||
_min = min;
|
||||
_max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制一个新的对象
|
||||
/// </summary>
|
||||
/// <returns>新对象</returns>
|
||||
public ObservableRange<T> Copy()
|
||||
{
|
||||
return new(Min, Max);
|
||||
}
|
||||
|
||||
#region Other
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Min, Max);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is ObservableRange<T> temp
|
||||
&& EqualityComparer<T>.Default.Equals(Min, temp.Min)
|
||||
&& EqualityComparer<T>.Default.Equals(Max, temp.Max);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(ObservableRange<T>? other)
|
||||
{
|
||||
return Equals(obj: other);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator ==(ObservableRange<T> a, ObservableRange<T> b)
|
||||
{
|
||||
return Equals(a, b);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator !=(ObservableRange<T> a, ObservableRange<T> b)
|
||||
{
|
||||
return Equals(a, b) is not true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
89
VPet.Solution/Utils/ObservableRect.cs
Normal file
89
VPet.Solution/Utils/ObservableRect.cs
Normal file
@ -0,0 +1,89 @@
|
||||
namespace HKW.HKWUtils;
|
||||
|
||||
public class ObservableRect<T> : ObservableClass<ObservableRect<T>>, IEquatable<ObservableRect<T>>
|
||||
{
|
||||
private T _x;
|
||||
public T X
|
||||
{
|
||||
get => _x;
|
||||
set => SetProperty(ref _x, value);
|
||||
}
|
||||
|
||||
private T _y;
|
||||
public T Y
|
||||
{
|
||||
get => _y;
|
||||
set => SetProperty(ref _y, value);
|
||||
}
|
||||
|
||||
private T _width;
|
||||
public T Width
|
||||
{
|
||||
get => _width;
|
||||
set => SetProperty(ref _width, value);
|
||||
}
|
||||
|
||||
private T _heigth;
|
||||
public T Height
|
||||
{
|
||||
get => _heigth;
|
||||
set => SetProperty(ref _heigth, value);
|
||||
}
|
||||
|
||||
public ObservableRect() { }
|
||||
|
||||
public ObservableRect(T x, T y, T width, T hetght)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Width = width;
|
||||
Height = hetght;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制一个新的对象
|
||||
/// </summary>
|
||||
/// <returns>新对象</returns>
|
||||
public ObservableRect<T> Copy()
|
||||
{
|
||||
return new(X, Y, Width, Height);
|
||||
}
|
||||
|
||||
#region Other
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(X, Y, Width, Height);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is ObservableRect<T> temp
|
||||
&& EqualityComparer<T>.Default.Equals(X, temp.X)
|
||||
&& EqualityComparer<T>.Default.Equals(Y, temp.Y)
|
||||
&& EqualityComparer<T>.Default.Equals(Width, temp.Width)
|
||||
&& EqualityComparer<T>.Default.Equals(Height, temp.Height);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(ObservableRect<T>? other)
|
||||
{
|
||||
return Equals(obj: other);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator ==(ObservableRect<T> a, ObservableRect<T> b)
|
||||
{
|
||||
return Equals(a, b);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public static bool operator !=(ObservableRect<T> a, ObservableRect<T> b)
|
||||
{
|
||||
return Equals(a, b) is not true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
79
VPet.Solution/Utils/Utils.cs
Normal file
79
VPet.Solution/Utils/Utils.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace HKW.HKWUtils;
|
||||
|
||||
/// <summary>
|
||||
/// 工具
|
||||
/// </summary>
|
||||
public static class Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// 解码像素宽度
|
||||
/// </summary>
|
||||
public const int DecodePixelWidth = 250;
|
||||
|
||||
/// <summary>
|
||||
/// 解码像素高度
|
||||
/// </summary>
|
||||
public const int DecodePixelHeight = 250;
|
||||
public static char[] Separator { get; } = new char[] { '_' };
|
||||
|
||||
//public static BitmapImage LoadImageToStream(string imagePath)
|
||||
//{
|
||||
// BitmapImage bitmapImage = new();
|
||||
// bitmapImage.BeginInit();
|
||||
// bitmapImage.DecodePixelWidth = DecodePixelWidth;
|
||||
// try
|
||||
// {
|
||||
// bitmapImage.StreamSource = new StreamReader(imagePath).BaseStream;
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// bitmapImage.EndInit();
|
||||
// }
|
||||
// return bitmapImage;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 载入图片至内存流
|
||||
/// </summary>
|
||||
/// <param name="imagePath">图片路径</param>
|
||||
/// <returns></returns>
|
||||
public static BitmapImage LoadImageToMemoryStream(string imagePath)
|
||||
{
|
||||
BitmapImage bitmapImage = new();
|
||||
bitmapImage.BeginInit();
|
||||
try
|
||||
{
|
||||
var bytes = File.ReadAllBytes(imagePath);
|
||||
bitmapImage.StreamSource = new MemoryStream(bytes);
|
||||
bitmapImage.DecodePixelWidth = DecodePixelWidth;
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmapImage.EndInit();
|
||||
}
|
||||
return bitmapImage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 载入图片至内存流
|
||||
/// </summary>
|
||||
/// <param name="imageStream">图片流</param>
|
||||
/// <returns></returns>
|
||||
public static BitmapImage LoadImageToMemoryStream(Stream imageStream)
|
||||
{
|
||||
BitmapImage bitmapImage = new();
|
||||
bitmapImage.BeginInit();
|
||||
try
|
||||
{
|
||||
bitmapImage.StreamSource = imageStream;
|
||||
bitmapImage.DecodePixelWidth = DecodePixelWidth;
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmapImage.EndInit();
|
||||
}
|
||||
return bitmapImage;
|
||||
}
|
||||
}
|
@ -14,6 +14,8 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@ -39,7 +41,8 @@
|
||||
<HintPath>..\packages\LinePutScript.1.9.2\lib\net462\LinePutScript.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="LinePutScript.Localization.WPF, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\LinePutScript.Localization.WPF.1.0.6\lib\net462\LinePutScript.Localization.WPF.dll</HintPath>
|
||||
<HintPath>
|
||||
..\packages\LinePutScript.Localization.WPF.1.0.6\lib\net462\LinePutScript.Localization.WPF.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Panuon.WPF, Version=1.0.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Panuon.WPF.1.0.2\lib\net462\Panuon.WPF.dll</HintPath>
|
||||
@ -49,6 +52,7 @@
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
@ -67,7 +71,55 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Compile Include="Converters\BoolInverter.cs" />
|
||||
<Compile Include="Utils\ClearFocus.cs" />
|
||||
<Compile Include="Utils\ElementHelper.cs" />
|
||||
<Compile Include="Utils\FindTopParent.cs" />
|
||||
<Compile Include="ViewModels\CustomizedSettingsPageVM.cs" />
|
||||
<Compile Include="ViewModels\DiagnosticSettingsPageVM.cs" />
|
||||
<Compile Include="ViewModels\ModSettingsPageVM.cs" />
|
||||
<Compile Include="ViewModels\SystemSettingsPageVM.cs" />
|
||||
<Compile Include="Views\CustomizedSettingsPage.xaml.cs">
|
||||
<DependentUpon>CustomizedSettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\DiagnosticSettingsPage.xaml.cs">
|
||||
<DependentUpon>DiagnosticSettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ModSettingsPage.xaml.cs">
|
||||
<DependentUpon>ModSettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SystemSettingsPage.xaml.cs">
|
||||
<DependentUpon>SystemSettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="Converters.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Styles.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Templates.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\CustomizedSettingsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\DiagnosticSettingsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\GraphicsSettingsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\InteractiveSettingsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
@ -75,10 +127,67 @@
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
<Compile Include="ViewModels\GraphicsSettingsPageVM.cs" />
|
||||
<Compile Include="ViewModels\InteractiveSettingsPageVM.cs" />
|
||||
<Compile Include="ViewModels\MainWindowVM.cs" />
|
||||
<Compile Include="Views\GraphicsSettingsPage.xaml.cs">
|
||||
<DependentUpon>GraphicsSettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\InteractiveSettingsPage.xaml.cs">
|
||||
<DependentUpon>InteractiveSettingsPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Converters\BrushToMediaColorConverter.cs" />
|
||||
<Compile Include="Converters\CalculatorConverter.cs" />
|
||||
<Compile Include="Converters\EqualsConverter.cs" />
|
||||
<Compile Include="Converters\FalseToCollapsedConverter.cs" />
|
||||
<Compile Include="Converters\FalseToHiddenConverter.cs" />
|
||||
<Compile Include="Converters\MediaColorToBrushConverter.cs" />
|
||||
<Compile Include="Converters\NotEqualsConverter.cs" />
|
||||
<Compile Include="Converters\NullToFalseConverter.cs" />
|
||||
<Compile Include="Converters\StringFormatConverter.cs" />
|
||||
<Compile Include="Converters\RatioMarginConverter.cs" />
|
||||
<Compile Include="Converters\MaxConverter.cs" />
|
||||
<Compile Include="Converters\MarginConverter.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableClass\INotifyPropertyChangedX.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableClass\INotifyPropertyChangingX.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableClass\ObservableClass.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableClass\PropertyChangedXEventArgs.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableClass\PropertyChangedXEventHandler.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableClass\PropertyChangingXEventArgs.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableClass\PropertyChangingXEventHandler.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableCommand\ExecuteAsyncEventHandler.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableCommand\ExecuteEventHandler.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableCommand\NotifyReceivedEventHandler.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableCommand\ObservableCommand.cs" />
|
||||
<Compile Include="SimpleObservable\ObservableCommand\ObservableCommandT.cs" />
|
||||
<Compile Include="Utils\ObservableEnumFlags.cs" />
|
||||
<Compile Include="Utils\Expansions.cs" />
|
||||
<Compile Include="Utils\HashCode.cs" />
|
||||
<Compile Include="Utils\ObservableRange.cs" />
|
||||
<Compile Include="Utils\ObservablePoint.cs" />
|
||||
<Compile Include="Utils\ObservableRect.cs" />
|
||||
<Compile Include="Utils\Utils.cs" />
|
||||
<Compile Include="Resources\NativeResources.cs" />
|
||||
<Compile Include="Usings.cs" />
|
||||
<Page Include="NativeStyles.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
<ContainsDesignTimeResources>true</ContainsDesignTimeResources>
|
||||
</Page>
|
||||
<Compile Include="NativeStyles.xaml.cs">
|
||||
<DependentUpon>NativeStyles.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="Views\ModSettingsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SystemSettingsPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
@ -117,5 +226,8 @@
|
||||
<Name>VPet-Simulator.Windows.Interface</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Models\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
9
VPet.Solution/ViewModels/CustomizedSettingsPageVM.cs
Normal file
9
VPet.Solution/ViewModels/CustomizedSettingsPageVM.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPet.Solution.ViewModels;
|
||||
|
||||
public class CustomizedSettingsPageVM { }
|
9
VPet.Solution/ViewModels/DiagnosticSettingsPageVM.cs
Normal file
9
VPet.Solution/ViewModels/DiagnosticSettingsPageVM.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPet.Solution.ViewModels;
|
||||
|
||||
public class DiagnosticSettingsPageVM { }
|
9
VPet.Solution/ViewModels/GraphicsSettingsPageVM.cs
Normal file
9
VPet.Solution/ViewModels/GraphicsSettingsPageVM.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPet.Solution.ViewModels;
|
||||
|
||||
public class GraphicsSettingsPageVM { }
|
9
VPet.Solution/ViewModels/InteractiveSettingsPageVM.cs
Normal file
9
VPet.Solution/ViewModels/InteractiveSettingsPageVM.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPet.Solution.ViewModels;
|
||||
|
||||
public class InteractiveSettingsPageVM { }
|
22
VPet.Solution/ViewModels/MainWindowVM.cs
Normal file
22
VPet.Solution/ViewModels/MainWindowVM.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VPet_Simulator.Core;
|
||||
using VPet_Simulator.Windows.Interface;
|
||||
|
||||
namespace VPet.Solution.ViewModels;
|
||||
|
||||
public class MainWindowVM : ObservableClass<MainWindowVM>
|
||||
{
|
||||
public MainWindowVM() { }
|
||||
|
||||
public static void LoadSettings(string path)
|
||||
{
|
||||
foreach (var file in Directory.EnumerateFiles(path))
|
||||
{
|
||||
var setting = new Setting(path);
|
||||
}
|
||||
}
|
||||
}
|
9
VPet.Solution/ViewModels/ModSettingsPageVM.cs
Normal file
9
VPet.Solution/ViewModels/ModSettingsPageVM.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPet.Solution.ViewModels;
|
||||
|
||||
public class ModSettingsPageVM { }
|
9
VPet.Solution/ViewModels/SystemSettingsPageVM.cs
Normal file
9
VPet.Solution/ViewModels/SystemSettingsPageVM.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VPet.Solution.ViewModels;
|
||||
|
||||
public class SystemSettingsPageVM { }
|
57
VPet.Solution/Views/CustomizedSettingsPage.xaml
Normal file
57
VPet.Solution/Views/CustomizedSettingsPage.xaml
Normal file
@ -0,0 +1,57 @@
|
||||
<Page
|
||||
x:Class="VPet.Solution.Views.CustomizedSettingsPage"
|
||||
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"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pu="https://opensource.panuon.com/wpf-ui"
|
||||
xmlns:vm="clr-namespace:VPet.Solution.ViewModels"
|
||||
Title="CustomizedSettingsPage"
|
||||
d:DataContext="{d:DesignInstance Type=vm:CustomizedSettingsPageVM}"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<StackPanel>
|
||||
<TextBlock Background="{x:Null}" TextWrapping="Wrap">
|
||||
<Run
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Text="{ll:Str 自定义链接}" /><LineBreak />
|
||||
<Run Text="{ll:Str '在自定栏添加快捷方式/网页/快捷键, 可以便携启动想要的功能'}" /><LineBreak />
|
||||
<Run Text="{ll:Str '键盘快捷键编写方法请参考'}" /> <Hyperlink d:Click="sendkey_click">
|
||||
<Run Text="{ll:Str '键盘快捷键 通用注解'}" />
|
||||
</Hyperlink><LineBreak />
|
||||
<Run Text="{ll:Str '右键进行排序/删除等操作'}" />
|
||||
</TextBlock>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button
|
||||
x:Name="btn_DIY"
|
||||
Margin="4"
|
||||
Padding="1"
|
||||
d:Click="DIY_ADD_Click"
|
||||
pu:ButtonHelper.CornerRadius="4"
|
||||
Background="{DynamicResource SecondaryLight}"
|
||||
Content="{ll:Str 添加新链接}" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Margin="4"
|
||||
Padding="1"
|
||||
d:Click="DIY_Save_Click"
|
||||
pu:ButtonHelper.CornerRadius="4"
|
||||
Background="{DynamicResource SecondaryLight}"
|
||||
Content="{ll:Str 保存设置}" />
|
||||
</Grid>
|
||||
<ScrollViewer>
|
||||
<StackPanel x:Name="StackDIY" />
|
||||
</ScrollViewer>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
@ -13,21 +13,14 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace VPet.Solution
|
||||
namespace VPet.Solution.Views;
|
||||
/// <summary>
|
||||
/// CustomizedSettingsPage.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CustomizedSettingsPage : Page
|
||||
{
|
||||
/// <summary>
|
||||
/// MainWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
public CustomizedSettingsPage()
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
if (App.IsDone)
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
InitializeComponent();
|
||||
}
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
119
VPet.Solution/Views/DiagnosticSettingsPage.xaml
Normal file
119
VPet.Solution/Views/DiagnosticSettingsPage.xaml
Normal file
@ -0,0 +1,119 @@
|
||||
<Page
|
||||
x:Class="VPet.Solution.Views.DiagnosticSettingsPage"
|
||||
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"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pu="https://opensource.panuon.com/wpf-ui"
|
||||
xmlns:vm="clr-namespace:VPet.Solution.ViewModels"
|
||||
Title="DiagnosticSettingsPage"
|
||||
d:DataContext="{d:DesignInstance Type=vm:DiagnosticSettingsPageVM}"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<ScrollViewer>
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{x:Null}"
|
||||
TextWrapping="Wrap">
|
||||
<Run
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Text="{ll:Str 自动超模MOD优化}" /><LineBreak />
|
||||
<Run Text="{ll:Str '对于超模内容,游戏会自动计算合理价格\ 如果未使用任何超模数据,数据菜单栏将会显示图标方便您进行炫耀数据'}" />
|
||||
</TextBlock>
|
||||
<pu:Switch
|
||||
x:Name="swAutoCal"
|
||||
Grid.Column="2"
|
||||
Margin="20,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
d:Checked="swAutoCal_Checked"
|
||||
d:Unchecked="swAutoCal_Checked"
|
||||
Background="Transparent"
|
||||
BorderBrush="{DynamicResource PrimaryDark}"
|
||||
BoxHeight="18"
|
||||
BoxWidth="35"
|
||||
CheckedBackground="{DynamicResource Primary}"
|
||||
CheckedBorderBrush="{DynamicResource Primary}"
|
||||
CheckedToggleBrush="{DynamicResource DARKPrimaryText}"
|
||||
Content="{ll:Str '自动计算合理价格'}"
|
||||
ToggleBrush="{DynamicResource PrimaryDark}"
|
||||
ToggleShadowColor="{x:Null}"
|
||||
ToggleSize="14"
|
||||
ToolTip="{ll:Str '该选项重启后生效'}" />
|
||||
<TextBlock
|
||||
Margin="0,20,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{x:Null}"
|
||||
FontSize="13"
|
||||
TextWrapping="Wrap">
|
||||
<Run
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Text="{ll:Str 诊断与反馈}" /> <LineBreak />
|
||||
<Run Text="{ll:Str '选择要发送给 LBGame 的诊断数据,诊断数据用于保护和及时更新 虚拟桌宠模拟器, 解决问题并改进产品.'}" /><LineBreak />
|
||||
<Run Text="{ll:Str '无论选择哪个选项,游戏都可以安全正常地运行.'}" /> <Hyperlink d:Click="hyper_moreInfo">
|
||||
<Run Text="{ll:Str 获取有关这些设置的更多信息}" />
|
||||
</Hyperlink>
|
||||
<LineBreak /> <Run FontWeight="Bold" Text="{ll:Str '当前存档Hash验证信息'}" />
|
||||
:<Run
|
||||
x:Name="RHashCheck"
|
||||
FontWeight="Bold"
|
||||
Text="通过" />
|
||||
</TextBlock>
|
||||
<RadioButton
|
||||
x:Name="RBDiagnosisYES"
|
||||
Margin="10,10,10,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:Checked="RBDiagnosisYES_Checked"
|
||||
Content="{ll:Str '发送诊断数据: 发送游戏存档, 包括饱腹,状态等各种游戏内\ 数据. 可能会包括该游戏内存和CPU使用情况'}"
|
||||
GroupName="diagnosis"
|
||||
Style="{DynamicResource StandardRadioButtonStyle}" />
|
||||
<RadioButton
|
||||
x:Name="RBDiagnosisNO"
|
||||
Margin="10,10,10,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:Checked="RBDiagnosisNO_Checked"
|
||||
Content="{ll:Str '不发送诊断数据: 适用于启用修改器,修改过游戏数据等不\ 符合分析数据条件. 或不希望提供游戏数据的玩家'}"
|
||||
GroupName="diagnosis"
|
||||
IsChecked="True"
|
||||
Style="{DynamicResource StandardRadioButtonStyle}" />
|
||||
<TextBlock
|
||||
Margin="0,15,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{x:Null}"
|
||||
TextWrapping="Wrap">
|
||||
<Run FontWeight="Bold" Text="{ll:Str 反馈频率}" /><LineBreak />
|
||||
<Run Text="{ll:Str 'VOS 应寻求我反馈按以下频率'}" />
|
||||
</TextBlock>
|
||||
<ComboBox
|
||||
x:Name="CBDiagnosis"
|
||||
Width="200"
|
||||
Margin="10,5,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:SelectionChanged="CBDiagnosis_SelectionChanged"
|
||||
IsEnabled="False"
|
||||
SelectedIndex="1"
|
||||
Style="{DynamicResource StandardComboBoxStyle}">
|
||||
<ComboBoxItem Content="{ll:Str '每 两百 周期一次'}" />
|
||||
<ComboBoxItem Content="{ll:Str '每 五百 周期一次'}" />
|
||||
<ComboBoxItem Content="{ll:Str '每 一千 周期一次'}" />
|
||||
<ComboBoxItem Content="{ll:Str '每 两千 周期一次'}" />
|
||||
<ComboBoxItem Content="{ll:Str '每 五千 周期一次'}" />
|
||||
<ComboBoxItem Content="{ll:Str '每 一万 周期一次'}" />
|
||||
<ComboBoxItem Content="{ll:Str '每 两万 周期一次'}" />
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
26
VPet.Solution/Views/DiagnosticSettingsPage.xaml.cs
Normal file
26
VPet.Solution/Views/DiagnosticSettingsPage.xaml.cs
Normal file
@ -0,0 +1,26 @@
|
||||
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;
|
||||
|
||||
namespace VPet.Solution.Views;
|
||||
/// <summary>
|
||||
/// DiagnosticSettingsPage.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class DiagnosticSettingsPage : Page
|
||||
{
|
||||
public DiagnosticSettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
374
VPet.Solution/Views/GraphicsSettingsPage.xaml
Normal file
374
VPet.Solution/Views/GraphicsSettingsPage.xaml
Normal file
@ -0,0 +1,374 @@
|
||||
<Page
|
||||
x:Class="VPet.Solution.Views.GraphicsSettingsPage"
|
||||
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"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pu="https://opensource.panuon.com/wpf-ui"
|
||||
xmlns:vm="clr-namespace:VPet.Solution.ViewModels"
|
||||
Title="GraphicsSettingsPage"
|
||||
d:DataContext="{d:DesignInstance Type=vm:GraphicsSettingsPageVM}"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition MinWidth="300" />
|
||||
<!--<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" MinWidth="100" />-->
|
||||
</Grid.ColumnDefinitions>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str '置于顶层'}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<pu:Switch
|
||||
x:Name="TopMostBox"
|
||||
Grid.Column="1"
|
||||
d:Checked="TopMostBox_Checked"
|
||||
d:Unchecked="TopMostBox_Unchecked"
|
||||
Content="{ll:Str '将桌宠置于顶层'}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str '将桌宠置于顶层'}" />
|
||||
<pu:Switch
|
||||
x:Name="HitThroughBox"
|
||||
Grid.Column="2"
|
||||
d:Checked="HitThroughBox_Checked"
|
||||
d:Unchecked="HitThroughBox_Checked"
|
||||
Content="{ll:Str '鼠标穿透'}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str '鼠标将会穿过桌宠到下方内容,不打扰操作\ 该选项'}" />
|
||||
<pu:Switch
|
||||
x:Name="PetHelperBox"
|
||||
Grid.Column="3"
|
||||
d:Checked="PetHelperBox_Checked"
|
||||
d:Unchecked="PetHelperBox_Checked"
|
||||
Content="{ll:Str '快速切换'}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str '添加快速切换小标,切换顶层或穿透'}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="Language"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<ComboBox
|
||||
x:Name="LanguageBox"
|
||||
Grid.Column="1"
|
||||
d:SelectionChanged="LanguageBox_SelectionChanged"
|
||||
Style="{DynamicResource ComboBox_BaseStyle}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 更高缩放}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<pu:Switch
|
||||
x:Name="FullScreenBox"
|
||||
Grid.Column="1"
|
||||
d:Checked="FullScreenBox_Check"
|
||||
d:Unchecked="FullScreenBox_Check"
|
||||
Content="{ll:Str 支持更大缩放倍率}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str 解锁缩放限制}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" MinWidth="100" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 缩放等级}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Slider
|
||||
x:Name="Slider_Zoom"
|
||||
Grid.Column="1"
|
||||
Margin="10,0,10,0"
|
||||
VerticalAlignment="Center"
|
||||
d:PreviewMouseUp="Slider_Zoom_MouseUp"
|
||||
IsSnapToTickEnabled="True"
|
||||
LargeChange=".1"
|
||||
Maximum="3"
|
||||
Minimum="0.5"
|
||||
SmallChange="0.05"
|
||||
Style="{DynamicResource StandardSliderStyle}"
|
||||
TickFrequency="0.05"
|
||||
Value="1" />
|
||||
<pu:NumberInput
|
||||
Grid.Column="2"
|
||||
Foreground="{DynamicResource DARKPrimaryDarker}"
|
||||
Interval="0.1"
|
||||
Maximum="3"
|
||||
Minimum="0.5"
|
||||
Style="{DynamicResource NumberInput_BaseStyle}"
|
||||
Value="{Binding Value, ElementName=Slider_Zoom}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" MinWidth="100" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 渲染分辨率}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Slider
|
||||
x:Name="Slider_Resolution"
|
||||
Grid.Column="1"
|
||||
Margin="10,0,10,0"
|
||||
VerticalAlignment="Center"
|
||||
d:PreviewMouseUp="Slider_Resolution_MouseUp"
|
||||
IsSnapToTickEnabled="True"
|
||||
LargeChange="50"
|
||||
Maximum="1920"
|
||||
Minimum="200"
|
||||
SmallChange="20"
|
||||
Style="{DynamicResource StandardSliderStyle}"
|
||||
TickFrequency="10"
|
||||
ToolTip="{ll:Str '桌宠图形渲染的分辨率,越高图形越清晰\ 但是高分辨率会占用更多内存\ 重启后生效'}"
|
||||
Value="1000" />
|
||||
<pu:NumberInput
|
||||
Grid.Column="2"
|
||||
Interval="10"
|
||||
Maximum="1920"
|
||||
Minimum="200"
|
||||
Style="{DynamicResource NumberInput_BaseStyle}"
|
||||
ToolTip="{ll:Str '桌宠图形渲染的分辨率,越高图形越清晰\ 但是高分辨率会占用更多内存\ 重启后生效'}"
|
||||
Value="{Binding Value, ElementName=Slider_Resolution}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 主题}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<ComboBox
|
||||
x:Name="ThemeBox"
|
||||
Grid.Column="1"
|
||||
d:SelectionChanged="ThemeBox_SelectionChanged"
|
||||
IsEnabled="False"
|
||||
Style="{DynamicResource ComboBox_BaseStyle}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 字体}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<ComboBox
|
||||
x:Name="FontBox"
|
||||
Grid.Column="1"
|
||||
d:SelectionChanged="FontBox_SelectionChanged"
|
||||
IsEnabled="False"
|
||||
Style="{DynamicResource ComboBox_BaseStyle}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Grid.Row="8"
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 启动位置}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<pu:Switch
|
||||
x:Name="StartPlace"
|
||||
Grid.Column="1"
|
||||
d:Checked="StartPlace_Checked"
|
||||
d:Unchecked="StartPlace_Checked"
|
||||
Content="{ll:Str 保存为退出位置}"
|
||||
IsChecked="True"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str 游戏退出位置为下次桌宠启动出现的位置}" />
|
||||
<TextBox
|
||||
x:Name="TextBoxStartUpX"
|
||||
Grid.Column="2"
|
||||
Margin="0,0,5,0"
|
||||
d:TextChanged="TextBoxStartUp_TextChanged"
|
||||
pu:IconHelper.Margin="5,0,0,0"
|
||||
pu:TextBoxHelper.Icon="X"
|
||||
pu:TextBoxHelper.InputLimit="Digit"
|
||||
pu:TextBoxHelper.Watermark="{ll:Str X轴}"
|
||||
Style="{DynamicResource StandardTextBoxStyle}"
|
||||
ToolTip="{ll:Str X轴}" />
|
||||
<TextBox
|
||||
x:Name="TextBoxStartUpY"
|
||||
Grid.Column="3"
|
||||
Margin="0,0,5,0"
|
||||
d:TextChanged="TextBoxStartUp_TextChanged"
|
||||
pu:IconHelper.Margin="5,0,0,0"
|
||||
pu:TextBoxHelper.Icon="Y"
|
||||
pu:TextBoxHelper.InputLimit="Digit"
|
||||
pu:TextBoxHelper.Watermark="{ll:Str Y轴}"
|
||||
FontSize="16"
|
||||
Style="{DynamicResource StandardTextBoxStyle}"
|
||||
ToolTip="{ll:Str Y轴}" />
|
||||
<Button
|
||||
x:Name="BtnStartUpGet"
|
||||
Grid.Column="4"
|
||||
d:Click="BtnStartUpGet_Click"
|
||||
Content="{ll:Str 设为当前位置}"
|
||||
Style="{DynamicResource Button_BaseStyle}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 消息框}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<pu:Switch
|
||||
x:Name="SwitchMsgOut"
|
||||
Grid.Column="1"
|
||||
d:Checked="SwitchMsgOut_Checked"
|
||||
d:Unchecked="SwitchMsgOut_Checked"
|
||||
Content="{ll:Str 将消息框置于外部}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str 将消息框置于外部}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 开机启动}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<pu:Switch
|
||||
x:Name="StartUpBox"
|
||||
Grid.Column="1"
|
||||
d:Checked="StartUpBox_Checked"
|
||||
d:Unchecked="StartUpBox_Checked"
|
||||
Content="{ll:Str 开机启动}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str '该游戏随着开机启动该程序\ 如需卸载游戏\ 请关闭该选项'}" />
|
||||
<pu:Switch
|
||||
x:Name="StartUpSteamBox"
|
||||
Grid.Column="2"
|
||||
d:Checked="StartUpSteamBox_Checked"
|
||||
d:Unchecked="StartUpSteamBox_Checked"
|
||||
Content="{ll:Str 从Steam启动}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str '从Steam启动该游戏, 统计时长不能停'}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 宠物动画}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" MinHeight="30" />
|
||||
</Grid.RowDefinitions>
|
||||
<ComboBox
|
||||
x:Name="PetBox"
|
||||
d:SelectionChanged="PetBox_SelectionChanged"
|
||||
Style="{DynamicResource ComboBox_BaseStyle}"
|
||||
ToolTip="{ll:Str '加载的宠物动画,重启后生效'}" />
|
||||
<TextBlock
|
||||
x:Name="PetIntor"
|
||||
Grid.Row="1"
|
||||
Margin="10,5,10,5"
|
||||
VerticalAlignment="Center"
|
||||
Text="{ll:Str '动画描述...'}"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 隐藏窗口}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<pu:Switch
|
||||
x:Name="SwitchHideFromTaskControl"
|
||||
Grid.Column="1"
|
||||
d:Checked="SwitchHideFromTaskControl_OnChecked"
|
||||
d:Unchecked="SwitchHideFromTaskControl_OnChecked"
|
||||
Content="{ll:Str '在任务切换器中隐藏窗口'}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str '在Alt+Tab中隐藏'}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</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>
|
||||
</Page>
|
31
VPet.Solution/Views/GraphicsSettingsPage.xaml.cs
Normal file
31
VPet.Solution/Views/GraphicsSettingsPage.xaml.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using HKW.HKWUtils;
|
||||
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;
|
||||
|
||||
namespace VPet.Solution.Views;
|
||||
|
||||
/// <summary>
|
||||
/// GraphicsSettingsPage.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class GraphicsSettingsPage : Page
|
||||
{
|
||||
public GraphicsSettingsPageVM ViewModel => this.SetViewModel<GraphicsSettingsPageVM>().Value;
|
||||
|
||||
public GraphicsSettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
401
VPet.Solution/Views/InteractiveSettingsPage.xaml
Normal file
401
VPet.Solution/Views/InteractiveSettingsPage.xaml
Normal file
@ -0,0 +1,401 @@
|
||||
<Page
|
||||
x:Class="VPet.Solution.Views.InteractiveSettingsPage"
|
||||
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"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pu="https://opensource.panuon.com/wpf-ui"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:vm="clr-namespace:VPet.Solution.ViewModels"
|
||||
Title="InteractiveSettingsPage"
|
||||
d:DataContext="{d:DesignInstance Type=vm:InteractiveSettingsPageVM}"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
<Label
|
||||
Margin="5"
|
||||
HorizontalAlignment="Left"
|
||||
Content="{ll:Str 桌宠设置}"
|
||||
FontSize="16"
|
||||
FontWeight="Bold"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="{ll:Str 桌宠名称}" Style="{DynamicResource Label_BaseStyle}" />
|
||||
<TextBox
|
||||
x:Name="TextBoxPetName"
|
||||
Grid.Column="1"
|
||||
d:TextChanged="TextBoxPetName_TextChanged"
|
||||
Style="{DynamicResource StandardTextBoxStyle}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="{ll:Str 桌宠状态}" Style="{DynamicResource Label_BaseStyle}" />
|
||||
<pu:Switch
|
||||
x:Name="Switch_EnablePetState"
|
||||
Grid.Column="1"
|
||||
d:Checked="CalFunctionBox_Checked"
|
||||
d:Unchecked="CalFunctionBox_Checked"
|
||||
Content="{ll:Str '启用桌宠状态'}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str '启用数据计算,桌宠会有状态变化,需要按时投喂等.\ 如果嫌麻烦可以关掉'}" />
|
||||
<!-- TODO: ComboBox使用内部数据 -->
|
||||
<ComboBox
|
||||
Grid.Column="2"
|
||||
d:SelectionChanged="combCalFunState_SelectionChanged"
|
||||
pu:ComboBoxHelper.Watermark="{ll:Str '当关闭数据计算时\ 桌宠显示的状态'}"
|
||||
IsEnabled="{Binding IsChecked, ElementName=Switch_EnablePetState, Converter={StaticResource BoolInverter}}"
|
||||
SelectedIndex="0"
|
||||
Style="{DynamicResource ComboBox_BaseStyle}"
|
||||
ToolTip="{ll:Str '当关闭数据计算时\ 桌宠显示的状态'}">
|
||||
<ComboBoxItem Content="Happy" />
|
||||
<ComboBoxItem Content="Nomal" />
|
||||
<ComboBoxItem Content="PoorCondition" />
|
||||
<ComboBoxItem Content="Ill" />
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="{ll:Str 长按间隔}" Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Slider
|
||||
x:Name="PressLengthSlider"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
d:ValueChanged="PressLengthSlider_ValueChanged"
|
||||
LargeChange="0.1"
|
||||
Maximum="5"
|
||||
Minimum="0.05"
|
||||
SmallChange=".05"
|
||||
Style="{DynamicResource Slider_BaseStyle}"
|
||||
TickFrequency="0.01"
|
||||
Value="0.5" />
|
||||
<pu:NumberInput
|
||||
Grid.Column="2"
|
||||
Interval="0.1"
|
||||
Maximum="5"
|
||||
Minimum="0.05"
|
||||
Style="{DynamicResource NumberInput_BaseStyle}"
|
||||
Value="{Binding Value, ElementName=PressLengthSlider}" />
|
||||
<TextBlock
|
||||
Grid.Column="3"
|
||||
Margin="0,5,10,5"
|
||||
Style="{DynamicResource TextBlock_BaseStyle}"
|
||||
Text="{ll:Str 秒}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="{ll:Str 计算间隔}" Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Slider
|
||||
x:Name="Slider_Cal"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
d:ValueChanged="CalSlider_ValueChanged"
|
||||
LargeChange="1"
|
||||
Maximum="60"
|
||||
Minimum="5"
|
||||
SmallChange=".5"
|
||||
Style="{DynamicResource Slider_BaseStyle}"
|
||||
TickFrequency="0.1"
|
||||
Value="15" />
|
||||
<pu:NumberInput
|
||||
Grid.Column="2"
|
||||
Interval="0.5"
|
||||
Maximum="60"
|
||||
Minimum="5"
|
||||
Style="{DynamicResource NumberInput_BaseStyle}"
|
||||
Value="{Binding Value, ElementName=Slider_Cal}" />
|
||||
<TextBlock
|
||||
Grid.Column="3"
|
||||
Margin="0,5,10,5"
|
||||
Style="{DynamicResource TextBlock_BaseStyle}"
|
||||
Text="{ll:Str 秒}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40" ToolTip="{ll:Str 互动周期决定在交互结束后大约经历多少计算间隔后再次进行自主行动}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="{ll:Str 互动周期}" Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Slider
|
||||
x:Name="Slider_Interaction"
|
||||
d:ValueChanged="Slider_Interaction_ValueChanged"
|
||||
LargeChange="5"
|
||||
Maximum="1000"
|
||||
Minimum="30"
|
||||
SmallChange="1"
|
||||
Style="{DynamicResource Slider_BaseStyle}"
|
||||
TickFrequency="1"
|
||||
ToolTip="{ll:Str '数据计算和互动计算时间间隔,间隔越短需要互动的频率可能会增加.\ 间隔越大越不容易打扰到当前工作'}"
|
||||
Value="200" />
|
||||
<pu:NumberInput
|
||||
Grid.Column="1"
|
||||
Interval="1"
|
||||
Maximum="1000"
|
||||
Minimum="30"
|
||||
Style="{DynamicResource NumberInput_BaseStyle}"
|
||||
Value="{Binding ElementName=Slider_Interaction, Path=Value}" />
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
Margin="0,5,10,5"
|
||||
Style="{DynamicResource TextBlock_BaseStyle}"
|
||||
Text="{ll:Str 秒}" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="3"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{DynamicResource TextBlock_BaseStyle}">
|
||||
<Run Text="{ll:Str 每分钟计算}" /> <Run x:Name="rTimeMinute">4</Run> <Run Text="{ll:Str 次数值变化}" />
|
||||
<Run Text="{ll:Str 大约}" /> <Run x:Name="RInter">4</Run> <Run Text="{ll:Str '分钟左右主动进行一次互动 (走路发呆爬墙等) '}" />
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid MinHeight="40" ToolTip="{ll:Str '当玩家在指定时间未对桌宠进行交互的时候,智能禁用移动功能\ 将在下次交互时解除'}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="{ll:Str 桌宠移动}" Style="{DynamicResource Label_BaseStyle}" />
|
||||
<pu:Switch
|
||||
x:Name="Switch_PetMove"
|
||||
Grid.Column="1"
|
||||
d:Checked="Switch_PetMove_Checked"
|
||||
d:Unchecked="Switch_PetMove_Checked"
|
||||
Content="{ll:Str 启用桌宠移动}"
|
||||
Style="{DynamicResource Switch_BaseStyle}"
|
||||
ToolTip="{ll:Str '启用移动互动,桌宠会在屏幕上乱动,移动互动概率为普通互动的一半.\ 如果嫌麻烦可以关掉'}" />
|
||||
<pu:Switch
|
||||
x:Name="Switch_SmartPetMove"
|
||||
Grid.Column="2"
|
||||
d:Checked="SmartSwitch_PetMove_Checked"
|
||||
d:Unchecked="SmartSwitch_PetMove_Checked"
|
||||
Content="{ll:Str '智能移动'}"
|
||||
IsEnabled="{Binding ElementName=Switch_PetMove, Path=IsChecked}"
|
||||
Style="{DynamicResource Switch_BaseStyle}" />
|
||||
<ComboBox
|
||||
x:Name="CBSmartMove"
|
||||
Grid.Column="3"
|
||||
d:SelectionChanged="CBSmartMove_SelectionChanged"
|
||||
IsEnabled="{Binding IsChecked, ElementName=Switch_SmartPetMove}"
|
||||
SelectedIndex="5"
|
||||
Style="{DynamicResource StandardComboBoxStyle}"
|
||||
ToolTip="{ll:Str 智能移动判断时间间隔}">
|
||||
<!--<ComboBoxItem Content="{ll:Str '30 秒'}">
|
||||
<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"
|
||||
Style="{DynamicResource TextBlock_BaseStyle}"
|
||||
Text="{ll:Str 分钟}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="{ll:Str 移动范围}" Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock HorizontalAlignment="Left" Style="{DynamicResource TextBlock_BaseStyle}">
|
||||
<Run Text="{ll:Str '当前移动区域:'}" />
|
||||
<Run Text="{ll:Str '主屏幕'}" />
|
||||
</TextBlock>
|
||||
<Button
|
||||
x:Name="BtnSetMoveArea_Default"
|
||||
Grid.Row="1"
|
||||
d:Click="BtnSetMoveArea_Default_Click"
|
||||
Content="{ll:Str 重置为主屏幕}"
|
||||
Style="{DynamicResource Button_BaseStyle}"
|
||||
ToolTip="{ll:Str '设置桌宠只在主屏幕进行移动'}" />
|
||||
<Button
|
||||
x:Name="BtnSetMoveArea_DetectScreen"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
d:Click="BtnSetMoveArea_DetectScreen_Click"
|
||||
Content="{ll:Str 设为当前屏幕}"
|
||||
Style="{DynamicResource Button_BaseStyle}"
|
||||
ToolTip="{ll:Str '设置桌宠只在当前桌宠所在的屏幕范围进行移动'}" />
|
||||
<Button
|
||||
x:Name="BtnSetMoveArea_Window"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
d:Click="BtnSetMoveArea_Window_Click"
|
||||
Content="{ll:Str 自定移动范围}"
|
||||
Style="{DynamicResource Button_BaseStyle}"
|
||||
ToolTip="{ll:Str '手动设置桌宠可移动范围'}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Label
|
||||
Margin="5"
|
||||
HorizontalAlignment="Left"
|
||||
Content="{ll:Str 音乐识别设置}"
|
||||
FontSize="16"
|
||||
FontWeight="Bold"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Content="{ll:Str 触发音量}"
|
||||
Style="{DynamicResource Label_BaseStyle}"
|
||||
ToolTip="{ll:Str 当实时播放音量达到该值时运行音乐动作}" />
|
||||
<Slider
|
||||
x:Name="VoiceCatchSilder"
|
||||
Grid.Column="1"
|
||||
d:ValueChanged="VoiceCatchSilder_ValueChanged"
|
||||
LargeChange="5"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
SmallChange="1"
|
||||
Style="{DynamicResource Slider_BaseStyle}"
|
||||
TickFrequency="1"
|
||||
ToolTip="{ll:Str 当实时播放音量达到该值时运行音乐动作}"
|
||||
Value="30" />
|
||||
<pu:NumberInput
|
||||
Grid.Column="2"
|
||||
Interval="1"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
Style="{DynamicResource NumberInput_BaseStyle}"
|
||||
ToolTip="{ll:Str 当实时播放音量达到该值时运行特殊音乐动作}"
|
||||
Value="{Binding Value, ElementName=VoiceCatchSilder}" />
|
||||
<TextBlock
|
||||
Grid.Column="3"
|
||||
Margin="0,5,10,5"
|
||||
Text="%" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Content="{ll:Str 高潮音量}"
|
||||
Style="{DynamicResource Label_BaseStyle}"
|
||||
ToolTip="{ll:Str 当实时播放音量达到该值时运行音乐动作}" />
|
||||
<Slider
|
||||
x:Name="VoiceMaxSilder"
|
||||
Grid.Column="1"
|
||||
d:ValueChanged="VoiceCatchSilder_ValueChanged"
|
||||
LargeChange="1"
|
||||
Maximum="100"
|
||||
Minimum="{Binding ElementName=VoiceCatchSilder, Path=Value}"
|
||||
SmallChange="1"
|
||||
Style="{DynamicResource StandardSliderStyle}"
|
||||
TickFrequency="1"
|
||||
ToolTip="{ll:Str 当实时播放音量达到该值时运行特殊音乐动作}"
|
||||
Value="75" />
|
||||
<pu:NumberInput
|
||||
Grid.Column="2"
|
||||
Foreground="{DynamicResource DARKPrimaryDarker}"
|
||||
Interval="1"
|
||||
Maximum="100"
|
||||
Minimum="{Binding ElementName=VoiceCatchSilder, Path=Value}"
|
||||
Style="{DynamicResource NumberInput_BaseStyle}"
|
||||
ToolTip="{ll:Str 当实时播放音量达到该值时运行特殊音乐动作}"
|
||||
Value="{Binding Value, ElementName=VoiceMaxSilder}" />
|
||||
<TextBlock
|
||||
Grid.Column="3"
|
||||
Margin="0,5,10,5"
|
||||
Text="%" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
26
VPet.Solution/Views/InteractiveSettingsPage.xaml.cs
Normal file
26
VPet.Solution/Views/InteractiveSettingsPage.xaml.cs
Normal file
@ -0,0 +1,26 @@
|
||||
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;
|
||||
|
||||
namespace VPet.Solution.Views;
|
||||
/// <summary>
|
||||
/// InteractiveSettingsPage.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class InteractiveSettingsPage : Page
|
||||
{
|
||||
public InteractiveSettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
118
VPet.Solution/Views/MainWindow.xaml
Normal file
118
VPet.Solution/Views/MainWindow.xaml
Normal file
@ -0,0 +1,118 @@
|
||||
<pu:WindowX
|
||||
x:Class="VPet.Solution.Views.MainWindow"
|
||||
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"
|
||||
Title="{ll:Str 'VPET 问题解决工具'}"
|
||||
Width="800"
|
||||
Height="450"
|
||||
MinWidth="400"
|
||||
MinHeight="200"
|
||||
d:DataContext="{d:DesignInstance Type=vm:MainWindowVM}"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid>
|
||||
<ListBox x:Name="ListBox_Saves" />
|
||||
</Grid>
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<ListBox x:Name="ListBox_Main" Style="{DynamicResource SideMenuListBoxStyle}">
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
<ListBoxItem x:Name="ListBoxItem_GraphicsSettings" Content="{ll:Str 图形}" />
|
||||
<ListBoxItem x:Name="ListBoxItem_SystemSettings" Content="{ll:Str 系统}" />
|
||||
<ListBoxItem x:Name="ListBoxItem_InteractiveSettings" Content="{ll:Str 互动}" />
|
||||
<ListBoxItem x:Name="ListBoxItem_CustomizedSettings" Content="{ll:Str 自定}" />
|
||||
<ListBoxItem x:Name="ListBoxItem_DiagnosticSettings" Content="{ll:Str 诊断}" />
|
||||
<ListBoxItem x:Name="ListBoxItem_ModSettings" Content="{ll:Str Mod管理}" />
|
||||
</ListBox>
|
||||
<Frame
|
||||
x:Name="Frame_Main"
|
||||
Grid.Row="1"
|
||||
Content="{Binding SelectedItem.Tag, ElementName=ListBox_Main}"
|
||||
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>
|
40
VPet.Solution/Views/MainWindow.xaml.cs
Normal file
40
VPet.Solution/Views/MainWindow.xaml.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using HKW.HKWUtils;
|
||||
using Panuon.WPF.UI;
|
||||
using System.Windows.Controls;
|
||||
using VPet.Solution.ViewModels;
|
||||
|
||||
namespace VPet.Solution.Views;
|
||||
|
||||
/// <summary>
|
||||
/// MainWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainWindow : WindowX
|
||||
{
|
||||
public MainWindowVM ViewModel => this.SetViewModel<MainWindowVM>().Value;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
if (App.IsDone)
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
InitializeComponent();
|
||||
ListBoxItem_GraphicsSettings.Tag = new GraphicsSettingsPage();
|
||||
ListBoxItem_SystemSettings.Tag = new SystemSettingsPage();
|
||||
ListBoxItem_InteractiveSettings.Tag = new InteractiveSettingsPage();
|
||||
ListBoxItem_CustomizedSettings.Tag = new CustomizedSettingsPage();
|
||||
ListBoxItem_DiagnosticSettings.Tag = new DiagnosticSettingsPage();
|
||||
ListBoxItem_ModSettings.Tag = new ModSettingsPage();
|
||||
}
|
||||
|
||||
private void Frame_Main_ContentRendered(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is not Frame frame)
|
||||
return;
|
||||
// 清理过时页面
|
||||
while (frame.CanGoBack)
|
||||
frame.RemoveBackEntry();
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
235
VPet.Solution/Views/ModSettingsPage.xaml
Normal file
235
VPet.Solution/Views/ModSettingsPage.xaml
Normal file
@ -0,0 +1,235 @@
|
||||
<Page
|
||||
x:Class="VPet.Solution.Views.ModSettingsPage"
|
||||
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"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pu="https://opensource.panuon.com/wpf-ui"
|
||||
xmlns:vm="clr-namespace:VPet.Solution.ViewModels"
|
||||
Title="ModSettingsPage"
|
||||
d:DataContext="{d:DesignInstance Type=vm:GraphicsSettingsPageVM}"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="120" />
|
||||
<ColumnDefinition Width="15" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ListBox
|
||||
x:Name="ListMod"
|
||||
VerticalAlignment="Top"
|
||||
d:SelectionChanged="ListMod_SelectionChanged"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
SelectionMode="Single"
|
||||
Style="{DynamicResource SideMenuListBoxStyle}" />
|
||||
<StackPanel Grid.Column="2">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="7" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
x:Name="ImageMOD"
|
||||
Width="120"
|
||||
Height="120"
|
||||
Margin="0,5,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Stretch="Fill" />
|
||||
<StackPanel Grid.Column="2">
|
||||
<Label
|
||||
x:Name="LabelModName"
|
||||
Margin="-5,2,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{x:Null}"
|
||||
Content="Core"
|
||||
FontSize="20"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource PrimaryText}" />
|
||||
<TextBlock Margin="0,0,0,0" TextWrapping="Wrap">
|
||||
<Run FontWeight="Bold" Text="{ll:Str '模组作者: '}" /><LineBreak />
|
||||
<Run x:Name="runMODAuthor" Text="LorisYounger" />
|
||||
<LineBreak /><Run FontWeight="Bold" Text="{ll:Str '模组版本: '}" /><Run x:Name="runMODVer" Text="1.0" />
|
||||
<LineBreak /><Run FontWeight="Bold" Text="{ll:Str '游戏版本: '}" /><Run x:Name="runMODGameVer" Text="1.0" />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Label
|
||||
Margin="-5,0,0,0"
|
||||
Padding="5,5,5,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Background="{x:Null}"
|
||||
Content="{ll:Str MOD介绍}"
|
||||
FontSize="18"
|
||||
FontWeight="Bold" />
|
||||
<ScrollViewer
|
||||
Height="80"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
pu:ScrollViewerHelper.ScrollBarThickness="10"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<TextBlock
|
||||
x:Name="GameInfo"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="14"
|
||||
Text="这里是MOD的介绍内容,你的介绍就是你的介绍
"
|
||||
TextWrapping="Wrap" />
|
||||
</ScrollViewer>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel>
|
||||
<Label
|
||||
Margin="-5,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Background="{x:Null}"
|
||||
Content="{ll:Str 内容}"
|
||||
FontSize="18"
|
||||
FontWeight="Bold" />
|
||||
<ScrollViewer
|
||||
Height="140"
|
||||
Margin="0,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
pu:ScrollViewerHelper.ScrollBarThickness="10"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<TextBlock
|
||||
x:Name="GameHave"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
FontSize="14"
|
||||
Text="该mod有许多功能
比如说功能1
比如说功能1
比如说功能1
比如说功能1
比如说功能1"
|
||||
TextWrapping="Wrap" />
|
||||
</ScrollViewer>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1">
|
||||
<Label
|
||||
Margin="-5,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{x:Null}"
|
||||
Content="{ll:Str 操作}"
|
||||
FontSize="18"
|
||||
FontWeight="Bold" />
|
||||
<TextBlock
|
||||
x:Name="ButtonOpenModFolder"
|
||||
Margin="0,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:MouseDown="ButtonOpenModFolder_MouseDown"
|
||||
Cursor="Hand"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource DARKPrimaryDarker}"
|
||||
Text="{ll:Str '所在文件夹'}"
|
||||
TextDecorations="Underline"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
x:Name="ButtonEnable"
|
||||
Margin="0,2,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:MouseDown="ButtonEnable_MouseDown"
|
||||
Cursor="Hand"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource DARKPrimaryDarker}"
|
||||
Text="{ll:Str '启用该模组'}"
|
||||
TextDecorations="Underline"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
x:Name="ButtonDisEnable"
|
||||
Margin="0,2,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:MouseDown="ButtonDisEnable_MouseDown"
|
||||
Cursor="Hand"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource DARKPrimaryDarker}"
|
||||
Text="{ll:Str '停用该模组'}"
|
||||
TextDecorations="Underline"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
x:Name="ButtonPublish"
|
||||
Margin="0,2,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:MouseDown="ButtonPublish_MouseDown"
|
||||
Cursor="Hand"
|
||||
FontSize="14"
|
||||
Foreground="DimGray"
|
||||
Text="{ll:Str 更新至Steam}"
|
||||
TextDecorations="Underline"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
x:Name="ButtonSteam"
|
||||
Margin="0,2,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:MouseDown="ButtonSteam_MouseDown"
|
||||
Cursor="Hand"
|
||||
FontSize="14"
|
||||
Foreground="DimGray"
|
||||
Text="{ll:Str 创意工坊页面}"
|
||||
TextDecorations="Underline"
|
||||
TextWrapping="Wrap" />
|
||||
<ProgressBar
|
||||
x:Name="ProgressBarUpload"
|
||||
Height="30"
|
||||
Margin="0,2,0,0"
|
||||
VerticalAlignment="Top"
|
||||
pu:ProgressBarHelper.CornerRadius="2"
|
||||
pu:ProgressBarHelper.IsPercentVisible="True"
|
||||
Background="{DynamicResource Primary}"
|
||||
BorderBrush="{DynamicResource PrimaryDarker}"
|
||||
BorderThickness="2"
|
||||
Foreground="{DynamicResource DARKPrimary}"
|
||||
Visibility="Collapsed"
|
||||
Value="60" />
|
||||
<TextBlock
|
||||
x:Name="ButtonSetting"
|
||||
Margin="0,2,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:MouseDown="ButtonSetting_MouseDown"
|
||||
Cursor="Hand"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource DARKPrimaryDarker}"
|
||||
Text="{ll:Str MOD设置}"
|
||||
TextDecorations="Underline"
|
||||
TextWrapping="Wrap" />
|
||||
<Button
|
||||
x:Name="ButtonAllow"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
d:Click="ButtonAllow_Click"
|
||||
Background="#FFFF2C2C"
|
||||
Content="{ll:Str 启用代码插件}"
|
||||
FontSize="12"
|
||||
Foreground="White"
|
||||
ToolTip="{ll:Str '启用该模组的代码内容,不能保证系统安全性'}" />
|
||||
</StackPanel>
|
||||
<Button
|
||||
x:Name="ButtonRestart"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="0,2,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
d:Click="ButtonRestart_Click"
|
||||
Background="{DynamicResource DARKPrimary}"
|
||||
Content="{ll:Str 重启软件以应用更改}"
|
||||
Foreground="{DynamicResource DARKPrimaryText}"
|
||||
Visibility="Collapsed" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
26
VPet.Solution/Views/ModSettingsPage.xaml.cs
Normal file
26
VPet.Solution/Views/ModSettingsPage.xaml.cs
Normal file
@ -0,0 +1,26 @@
|
||||
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;
|
||||
|
||||
namespace VPet.Solution.Views;
|
||||
/// <summary>
|
||||
/// ModSettingsPage.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class ModSettingsPage : Page
|
||||
{
|
||||
public ModSettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
326
VPet.Solution/Views/SystemSettingsPage.xaml
Normal file
326
VPet.Solution/Views/SystemSettingsPage.xaml
Normal file
@ -0,0 +1,326 @@
|
||||
<Page
|
||||
x:Class="VPet.Solution.Views.SystemSettingsPage"
|
||||
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"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pu="https://opensource.panuon.com/wpf-ui"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:vm="clr-namespace:VPet.Solution.ViewModels"
|
||||
Title="SystemSettingsPage"
|
||||
d:DataContext="{d:DesignInstance Type=vm:SystemSettingsPageVM}"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 自动保存频率}"
|
||||
Style="{DynamicResource Label_BaseStyle}"
|
||||
ToolTip="{ll:Str 在指定时间后自动保存游戏数据}" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Style="{DynamicResource TextBlock_BaseStyle}"
|
||||
Text="{ll:Str 每次间隔}" />
|
||||
<ComboBox
|
||||
x:Name="CBAutoSave"
|
||||
Grid.Column="2"
|
||||
d:SelectionChanged="CBAutoSave_SelectionChanged"
|
||||
SelectedIndex="3"
|
||||
Style="{DynamicResource ComboBox_BaseStyle}">
|
||||
<!--<ComboBoxItem Content="{ll:Str 关闭自动保存}">
|
||||
<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
|
||||
Grid.Column="3"
|
||||
Style="{DynamicResource TextBlock_BaseStyle}"
|
||||
Text="{ll:Str 分钟}" />
|
||||
</Grid>
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 备份设置}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Style="{DynamicResource TextBlock_BaseStyle}"
|
||||
Text="{ll:Str 备份数量}" />
|
||||
<pu:NumberInput
|
||||
x:Name="numBackupSaveMaxNum"
|
||||
Grid.Column="2"
|
||||
d:ValueChanged="numBackupSaveMaxNum_ValueChanged"
|
||||
Minimum="1"
|
||||
Style="{DynamicResource NumberInput_BaseStyle}"
|
||||
Value="20" />
|
||||
</Grid>
|
||||
<!--<Grid Margin="0,5,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="35" />
|
||||
<RowDefinition Height="35" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="15" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock
|
||||
Margin="0,6,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Background="{x:Null}"
|
||||
TextWrapping="Wrap">
|
||||
<Run
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Text="{ll:Str 从备份中还原}" /><LineBreak />
|
||||
<Run Text="{ll:Str '虚拟桌宠模拟器在每次保存的时候都会备份上次储存的存档, 当原始存档丢失,受损或误操作时, 就可以还原他们'}" />
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
VerticalAlignment="Center"
|
||||
Text="{ll:Str 加载存档}" />
|
||||
<Button
|
||||
x:Name="BtnSaveReload"
|
||||
Grid.Row="1"
|
||||
Grid.Column="3"
|
||||
Margin="5"
|
||||
Padding="1"
|
||||
d:Click="BtnSaveReload_Click"
|
||||
pu:ButtonHelper.CornerRadius="4"
|
||||
Background="{DynamicResource SecondaryLight}"
|
||||
Content="{ll:Str 加载}"
|
||||
ToolTip="{ll:Str 加载上次保存的存档}" />
|
||||
<ComboBox
|
||||
x:Name="CBSaveReLoad"
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
d:MouseEnter="CBSaveReLoad_MouseEnter"
|
||||
FontSize="16"
|
||||
SelectedIndex="3"
|
||||
Style="{DynamicResource StandardComboBoxStyle}" />
|
||||
</Grid>-->
|
||||
<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 聊天设置}"
|
||||
Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<RadioButton
|
||||
x:Name="RBCGPTUseLB"
|
||||
d:Checked="CGPType_Checked"
|
||||
Content="{ll:Str '使用桌宠选项式\ 聊天功能'}"
|
||||
GroupName="cgpttype"
|
||||
IsChecked="True"
|
||||
Style="{DynamicResource StandardRadioButtonStyle}"
|
||||
ToolTip="{ll:Str 支持MOD与创意工坊添加聊天内容}" />
|
||||
<RadioButton
|
||||
x:Name="RBCGPTClose"
|
||||
Grid.Column="1"
|
||||
d:Checked="CGPType_Checked"
|
||||
Content="{ll:Str '关闭聊天框'}"
|
||||
GroupName="cgpttype"
|
||||
Style="{DynamicResource StandardRadioButtonStyle}" />
|
||||
<Grid Grid.Row="1" Grid.ColumnSpan="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<RadioButton
|
||||
x:Name="RBCGPTDIY"
|
||||
d:Checked="CGPType_Checked"
|
||||
Content="{ll:Str '自定义聊天接口'}"
|
||||
GroupName="cgpttype"
|
||||
Style="{DynamicResource StandardRadioButtonStyle}" />
|
||||
<ComboBox
|
||||
x:Name="cbChatAPISelect"
|
||||
Grid.Column="1"
|
||||
d:SelectionChanged="cbChatAPISelect_SelectionChanged"
|
||||
Style="{DynamicResource ComboBox_BaseStyle}" />
|
||||
<Button
|
||||
x:Name="BtnCGPTReSet"
|
||||
Grid.Column="2"
|
||||
d:Click="ChatGPT_Reset_Click"
|
||||
Background="{DynamicResource SecondaryLight}"
|
||||
Content="{ll:Str 初始化桌宠聊天程序}"
|
||||
Style="{DynamicResource Button_BaseStyle}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<!--<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="15" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="35" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
x:Name="tbMode"
|
||||
Grid.Row="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{ll:Str 使用模式}" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
VerticalAlignment="Center"
|
||||
Text="{ll:Str 相关功能}" />
|
||||
<Grid Grid.Column="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
-->
|
||||
<!--<RadioButton x:Name="RBCGPTUseAPI" Grid.Column="1" Checked="CGPType_Checked"
|
||||
Content="{ll:Str '使用从ChatGPT\ 申请的的API'}" GroupName="cgpttype"
|
||||
Style="{DynamicResource StandardRadioButtonStyle}"
|
||||
ToolTip="{ll:Str 需要去OpenAI官网申请}" />-->
|
||||
<!--
|
||||
</Grid>
|
||||
</Grid>-->
|
||||
<!--<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label HorizontalContentAlignment="Left" h:ElementHelper.UniformMinWidthGroup="A" Content="{ll:Str 游戏操作}" Style="{DynamicResource Label_BaseStyle}" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
d:Click="save_click"
|
||||
Content="{ll:Str 保存游戏}"
|
||||
Style="{DynamicResource Button_BaseStyle}"
|
||||
ToolTip="{ll:Str '手动保存桌宠存档,就算不手动保存,桌宠也会在退出的时候自动保存'}" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
d:Click="restart_click"
|
||||
pu:ButtonHelper.CornerRadius="4"
|
||||
Content="{ll:Str 重新开始}"
|
||||
Style="{DynamicResource Button_BaseStyle}"
|
||||
ToolTip="{ll:Str '重新开始新游戏,重置统计等信息\ 对于想要获得脱离超模从而获得成就非常有帮助'}" />
|
||||
<Button
|
||||
x:Name="btn_cleancache"
|
||||
Grid.Column="3"
|
||||
d:Click="cleancache_click"
|
||||
pu:ButtonHelper.CornerRadius="4"
|
||||
Content="{ll:Str 清理缓存}"
|
||||
Style="{DynamicResource Button_BaseStyle}"
|
||||
ToolTip="{ll:Str '清理缓存的动画,声音文件'}" />
|
||||
</Grid>-->
|
||||
<!--<Grid MinHeight="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label HorizontalContentAlignment="Left"
|
||||
h:ElementHelper.UniformMinWidthGroup="A"
|
||||
Content="{ll:Str 桌宠多开}"
|
||||
Style="{DynamicResource Label_BaseStyle}"
|
||||
ToolTip="{ll:Str '支持多开多个桌宠, 这些桌宠将会有独立的设置与存档\ 如果画师能够足够勤奋,未来可以看到这些多开的桌宠之间的互动'}" />
|
||||
-->
|
||||
<!-- 新建要弹个窗写入存档名称 -->
|
||||
<!--
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
d:Click="btn_mutinew_click"
|
||||
Content="{ll:Str 新建存档}"
|
||||
Style="{DynamicResource Button_BaseStyle}"
|
||||
ToolTip="{ll:Str 新建多开存档}" />
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
d:Click="btn_muti_open_click"
|
||||
Content="{ll:Str 打开存档}"
|
||||
Style="{DynamicResource Button_BaseStyle}"
|
||||
ToolTip="{ll:Str 打开当前选择的多开存档}" />
|
||||
-->
|
||||
<!-- 存档列表, 或许应该用个大一点的 -->
|
||||
<!--
|
||||
<ComboBox Grid.Column="3" Style="{DynamicResource ComboBox_BaseStyle}" />
|
||||
<Button
|
||||
x:Name="btn_mutidel"
|
||||
Grid.Column="4"
|
||||
d:Click="btn_mutidel_Click"
|
||||
Content="{ll:Str 删除存档}"
|
||||
Style="{DynamicResource Button_BaseStyle}"
|
||||
ToolTip="{ll:Str 删除当前选择的多开存档}" />
|
||||
</Grid>-->
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
26
VPet.Solution/Views/SystemSettingsPage.xaml.cs
Normal file
26
VPet.Solution/Views/SystemSettingsPage.xaml.cs
Normal file
@ -0,0 +1,26 @@
|
||||
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;
|
||||
|
||||
namespace VPet.Solution.Views;
|
||||
/// <summary>
|
||||
/// SystemSettingsPage.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class SystemSettingsPage : Page
|
||||
{
|
||||
public SystemSettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user