mirror of
https://github.com/ZuneDev/ZuneModdingHelper.git
synced 2026-07-27 13:12:21 -07:00
Better apply/reset flow in backend
This commit is contained in:
+78
-10
@@ -18,13 +18,18 @@ namespace ZuneModCore
|
||||
|
||||
public abstract string Author { get; }
|
||||
|
||||
public delegate void StatusChangedHandler(Mod sender, bool status);
|
||||
public event StatusChangedHandler? StatusChanged;
|
||||
|
||||
public virtual AbstractUICollection? GetDefaultOptionsUI() => null;
|
||||
|
||||
public virtual Task Init() => Task.CompletedTask;
|
||||
|
||||
public abstract Task<string?> Apply();
|
||||
protected abstract Task<string?> ApplyCore();
|
||||
|
||||
public abstract Task<string?> Reset();
|
||||
protected abstract Task<string?> ResetCore();
|
||||
|
||||
protected virtual void FireStatusChanged(bool status) => StatusChanged?.Invoke(this, status);
|
||||
|
||||
private AbstractUICollection? _OptionsUI;
|
||||
public AbstractUICollection? OptionsUI
|
||||
@@ -38,6 +43,10 @@ namespace ZuneModCore
|
||||
set => _OptionsUI = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a directory that mods can use to store mod-specific information,
|
||||
/// such as backups for resetting.
|
||||
/// </summary>
|
||||
public string StorageDirectory
|
||||
{
|
||||
get
|
||||
@@ -51,12 +60,29 @@ namespace ZuneModCore
|
||||
|
||||
public abstract IReadOnlyList<ModDependency>? DependentMods { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Applies this mod, without any of its dependencies.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The error message if not successful.
|
||||
/// </returns>
|
||||
public async Task<string?> Apply()
|
||||
{
|
||||
string? error = await ApplyCore();
|
||||
if (error == null)
|
||||
{
|
||||
ModManager.MarkApplied(Id);
|
||||
FireStatusChanged(true);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes any missing depedencies.
|
||||
/// </summary>
|
||||
public Task InitDependencies() => ForAllDependencies(async mod =>
|
||||
public Task InitDependencies() => ForAllDependenciesAsync(async mod =>
|
||||
{
|
||||
bool isDepApplied = await mod.CheckApplied();
|
||||
bool isDepApplied = mod.CheckApplied();
|
||||
if (!isDepApplied)
|
||||
await mod.Init();
|
||||
});
|
||||
@@ -67,16 +93,58 @@ namespace ZuneModCore
|
||||
/// <remarks>
|
||||
/// Make sure to call <see cref="InitDependencies"/> first.
|
||||
/// </remarks>
|
||||
public Task ApplyDependencies() => ForAllDependencies(async mod =>
|
||||
public Task ApplyDependencies() => ForAllDependenciesAsync(async mod =>
|
||||
{
|
||||
bool isDepApplied = await mod.CheckApplied();
|
||||
bool isDepApplied = mod.CheckApplied();
|
||||
if (!isDepApplied)
|
||||
await mod.Apply();
|
||||
});
|
||||
|
||||
public Task<bool> CheckApplied() => TrueForAllDependencies(mod => mod.CheckApplied());
|
||||
/// <summary>
|
||||
/// Applies this mod and all its dependencies.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The error message if not successful.
|
||||
/// </returns>
|
||||
public async Task<string?> ApplyWithDependencies()
|
||||
{
|
||||
await ApplyDependencies();
|
||||
return await Apply();
|
||||
}
|
||||
|
||||
private async Task ForAllDependencies(Func<Mod, Task> asyncAction)
|
||||
/// <summary>
|
||||
/// Resets this mod, without resetting any dependencies.
|
||||
/// </summary>
|
||||
public async Task<string?> Reset()
|
||||
{
|
||||
string? error = await ResetCore();
|
||||
if (error == null)
|
||||
{
|
||||
ModManager.MarkReset(Id);
|
||||
FireStatusChanged(false);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
public bool CheckApplied() => ModManager.CheckStatus(Id);
|
||||
|
||||
public bool CheckDependenciesApplied() => TrueForAllDependencies(mod => mod.CheckApplied());
|
||||
|
||||
private void ForAllDependencies(Action<Mod> action)
|
||||
{
|
||||
// Check if there are any dependencies
|
||||
if (DependentMods == null)
|
||||
return;
|
||||
|
||||
foreach (var dep in DependentMods)
|
||||
{
|
||||
var depMod = ModManager.AvailableMods.First(m => m.Id == dep.Id);
|
||||
if (depMod != null)
|
||||
action(depMod);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ForAllDependenciesAsync(Func<Mod, Task> asyncAction)
|
||||
{
|
||||
// Check if there are any dependencies
|
||||
if (DependentMods == null)
|
||||
@@ -90,7 +158,7 @@ namespace ZuneModCore
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> TrueForAllDependencies(Func<Mod, Task<bool>> asyncAction)
|
||||
private bool TrueForAllDependencies(Func<Mod, bool> action)
|
||||
{
|
||||
// Check if there are any dependencies
|
||||
if (DependentMods == null)
|
||||
@@ -100,7 +168,7 @@ namespace ZuneModCore
|
||||
{
|
||||
var depMod = ModManager.AvailableMods.First(m => m.Id == dep.Id);
|
||||
if (depMod != null)
|
||||
if (!await asyncAction(depMod))
|
||||
if (!action(depMod))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
@@ -26,9 +27,7 @@ namespace ZuneModCore
|
||||
[Obsolete]
|
||||
internal ModDependency() { }
|
||||
|
||||
public Task<bool> CheckStatusAsync() => ModManager.CheckStatus(Id);
|
||||
|
||||
private bool CheckStatus() => CheckStatusAsync().Result;
|
||||
public bool CheckStatus() => ModManager.CheckStatus(Id);
|
||||
|
||||
public override string ToString() => $"{Id} / {Version}";
|
||||
}
|
||||
|
||||
+28
-15
@@ -33,21 +33,19 @@ namespace ZuneModCore
|
||||
/// <summary>
|
||||
/// Marks the specified mod as applied in the status file.
|
||||
/// </summary>
|
||||
internal static Task MarkApplied(string modId) => MarkStatus(modId, true);
|
||||
internal static void MarkApplied(string modId) => MarkStatus(modId, true);
|
||||
|
||||
/// <summary>
|
||||
/// Marks the specified mod as reset in the status file.
|
||||
/// </summary>
|
||||
internal static Task MarkReset(string modId) => MarkStatus(modId, false);
|
||||
internal static void MarkReset(string modId) => MarkStatus(modId, false);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the status of the specified mod in the status file.
|
||||
/// </summary>
|
||||
private static async Task MarkStatus(string modId, bool status)
|
||||
private static void MarkStatus(string modId, bool status)
|
||||
{
|
||||
using var stream = File.Open(CoreStatusFile, FileMode.OpenOrCreate);
|
||||
var model = await JsonSerializer.DeserializeAsync<StatusModel>(stream);
|
||||
Guard.IsNotNull(model, nameof(model));
|
||||
var model = GetOrCreateStatusModel();
|
||||
|
||||
bool curStatus = model.InstalledMods.ContainsKey(modId);
|
||||
if (curStatus && !status)
|
||||
@@ -59,22 +57,37 @@ namespace ZuneModCore
|
||||
model.InstalledMods.Add(modId, CurrentVersion);
|
||||
}
|
||||
|
||||
await JsonSerializer.SerializeAsync(stream, model);
|
||||
string json = JsonSerializer.Serialize(model);
|
||||
File.WriteAllText(CoreStatusFile, json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status of the specified mod from the status file.
|
||||
/// </summary>
|
||||
internal static async Task<bool> CheckStatus(string modId)
|
||||
internal static bool CheckStatus(string modId)
|
||||
{
|
||||
if (!File.Exists(CoreStatusFile))
|
||||
return false;
|
||||
|
||||
using var stream = File.OpenRead(CoreStatusFile);
|
||||
var model = await JsonSerializer.DeserializeAsync<StatusModel>(stream);
|
||||
Guard.IsNotNull(model, nameof(model));
|
||||
|
||||
var model = GetOrCreateStatusModel();
|
||||
return model.InstalledMods.ContainsKey(modId);
|
||||
}
|
||||
|
||||
private static StatusModel GetOrCreateStatusModel()
|
||||
{
|
||||
StatusModel? model = null;
|
||||
if (File.Exists(CoreStatusFile))
|
||||
{
|
||||
string json = File.ReadAllText(CoreStatusFile);
|
||||
if (!string.IsNullOrWhiteSpace(json))
|
||||
model = JsonSerializer.Deserialize<StatusModel>(json);
|
||||
}
|
||||
|
||||
model ??= new()
|
||||
{
|
||||
Version = CurrentVersion,
|
||||
InstalledMods = new()
|
||||
};
|
||||
|
||||
Guard.IsNotNull(model, nameof(model));
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
using Microsoft.Toolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.Toolkit.Mvvm.Input;
|
||||
using OwlCore.AbstractUI.Models;
|
||||
using OwlCore.AbstractUI.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ZuneModCore
|
||||
{
|
||||
public class ModViewModel : ObservableObject, IDisposable
|
||||
{
|
||||
public ModViewModel(Mod mod)
|
||||
{
|
||||
Mod = mod;
|
||||
_loadCommand = new AsyncRelayCommand(LoadAsync);
|
||||
_applyCommand = new AsyncRelayCommand(Mod.ApplyWithDependencies);
|
||||
_resetCommand = new AsyncRelayCommand(Mod.Reset);
|
||||
|
||||
if (Mod.OptionsUI != null)
|
||||
OptionsViewModel = new(Mod.OptionsUI);
|
||||
|
||||
Mod.StatusChanged += OnStatusChanged;
|
||||
}
|
||||
|
||||
private Mod _mod;
|
||||
private AbstractUICollectionViewModel? _optionsVm;
|
||||
private IAsyncRelayCommand _loadCommand;
|
||||
private IAsyncRelayCommand? _actionCommand;
|
||||
private bool _hasOptions;
|
||||
private bool _hasDependencies;
|
||||
private string _actionButtonText;
|
||||
private readonly IAsyncRelayCommand _applyCommand;
|
||||
private readonly IAsyncRelayCommand _resetCommand;
|
||||
|
||||
public Mod Mod
|
||||
{
|
||||
get => _mod;
|
||||
set
|
||||
{
|
||||
HasDependencies = _mod?.DependentMods != null && _mod.DependentMods.Count > 0;
|
||||
SetProperty(ref _mod, value);
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractUICollectionViewModel? OptionsViewModel
|
||||
{
|
||||
get => _optionsVm;
|
||||
set
|
||||
{
|
||||
HasOptions = _optionsVm != null;
|
||||
SetProperty(ref _optionsVm, value);
|
||||
}
|
||||
}
|
||||
|
||||
public IAsyncRelayCommand LoadCommand
|
||||
{
|
||||
get => _loadCommand;
|
||||
set => SetProperty(ref _loadCommand, value);
|
||||
}
|
||||
|
||||
public IAsyncRelayCommand? ActionCommand
|
||||
{
|
||||
get => _actionCommand;
|
||||
set => SetProperty(ref _actionCommand, value);
|
||||
}
|
||||
|
||||
public bool HasOptions
|
||||
{
|
||||
get => _hasOptions;
|
||||
set => SetProperty(ref _hasOptions, value);
|
||||
}
|
||||
|
||||
public bool HasDependencies
|
||||
{
|
||||
get => _hasDependencies;
|
||||
set => SetProperty(ref _hasDependencies, value);
|
||||
}
|
||||
|
||||
public string ActionButtonText
|
||||
{
|
||||
get => _actionButtonText;
|
||||
set => SetProperty(ref _actionButtonText, value);
|
||||
}
|
||||
|
||||
public async Task LoadAsync()
|
||||
{
|
||||
OnStatusChanged(_mod, _mod.CheckApplied());
|
||||
}
|
||||
|
||||
private void OnStatusChanged(Mod mod, bool status)
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
ActionButtonText = "Reset";
|
||||
ActionCommand = _resetCommand;
|
||||
}
|
||||
else
|
||||
{
|
||||
ActionButtonText = "Apply";
|
||||
ActionCommand = _applyCommand;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Mod.StatusChanged -= OnStatusChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace ZuneModCore.Mods
|
||||
|
||||
public override IReadOnlyList<ModDependency>? DependentMods => null;
|
||||
|
||||
public override async Task<string?> Apply()
|
||||
protected override async Task<string?> ApplyCore()
|
||||
{
|
||||
string bgimgPath = ((AbstractTextBox)OptionsUI!.Items[0]).Value;
|
||||
FileInfo bgimgInfo = new(bgimgPath);
|
||||
@@ -114,7 +114,7 @@ namespace ZuneModCore.Mods
|
||||
}
|
||||
}
|
||||
|
||||
public override Task<string?> Reset()
|
||||
protected override Task<string?> ResetCore()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using OwlCore.AbstractUI.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using ZuneModCore.Win32;
|
||||
|
||||
@@ -72,10 +73,13 @@ namespace ZuneModCore.Mods
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task<string?> Apply() => await Apply(false);
|
||||
protected override async Task<string?> ApplyCore() => await Apply(false);
|
||||
|
||||
public async Task<string?> Apply(bool applyAll = false)
|
||||
{
|
||||
// Save backup of current values
|
||||
ExportFeatureOverrides(Path.Combine(StorageDirectory, "FeatureOverrides.reg"));
|
||||
|
||||
// Use user choices from AbstractUI
|
||||
foreach (AbstractUIElement uiElem in OptionsUI!.Items)
|
||||
{
|
||||
@@ -84,7 +88,7 @@ namespace ZuneModCore.Mods
|
||||
bool isSuccess = SetFeatureOverride(boolElem.Id, true);
|
||||
if (!isSuccess)
|
||||
{
|
||||
string? resetStatus = await Reset();
|
||||
string? resetStatus = await ResetCore();
|
||||
if (resetStatus != null)
|
||||
{
|
||||
// The reset failed as well, return both errors
|
||||
@@ -101,13 +105,24 @@ namespace ZuneModCore.Mods
|
||||
return null;
|
||||
}
|
||||
|
||||
public override async Task<string?> Reset()
|
||||
protected override async Task<string?> ResetCore()
|
||||
{
|
||||
// Delete all values first, so if a backup exists it has a clean slate
|
||||
RegEdit.CurrentUserDeleteKey(ZUNE_FEATURESOVERRIDE_REGKEY);
|
||||
|
||||
FileInfo reg = new(Path.Combine(StorageDirectory, "FeatureOverrides.reg"));
|
||||
if (reg.Exists)
|
||||
{
|
||||
// Load backup of original values
|
||||
RegEdit.ImportKey(reg.FullName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void ExportFeatureOverrides(string path) =>
|
||||
RegEdit.ExportKey(RegEdit.HIVE_CURRENTUSER, ZUNE_FEATURESOVERRIDE_REGKEY, path);
|
||||
|
||||
public static bool SetFeatureOverride(string feature, bool value) =>
|
||||
RegEdit.CurrentUserSetBoolValue(ZUNE_FEATURESOVERRIDE_REGKEY, feature, value);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace ZuneModCore.Mods
|
||||
|
||||
public override IReadOnlyList<ModDependency>? DependentMods => null;
|
||||
|
||||
public override async Task<string?> Apply()
|
||||
protected override async Task<string?> ApplyCore()
|
||||
{
|
||||
// Use user choices from AbstractUI
|
||||
string folderPath = ((AbstractTextBox)OptionsUI!.Items[0]).Value;
|
||||
@@ -72,7 +72,7 @@ namespace ZuneModCore.Mods
|
||||
return null;
|
||||
}
|
||||
|
||||
public override Task<string?> Reset()
|
||||
protected override Task<string?> ResetCore()
|
||||
{
|
||||
return Task.FromResult<string?>(null);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using OwlCore.AbstractUI.Models;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using ZuneModCore.Win32;
|
||||
|
||||
@@ -23,7 +20,7 @@ namespace ZuneModCore.Mods
|
||||
|
||||
public override string Id => nameof(VideoSyncMod);
|
||||
|
||||
public override async Task<string?> Apply()
|
||||
protected override async Task<string?> ApplyCore()
|
||||
{
|
||||
// Make a backup of the original file
|
||||
FileVersionInfo wmvDllVersionInfo = FileVersionInfo.GetVersionInfo(WMVCORE_PATH);
|
||||
@@ -56,7 +53,7 @@ namespace ZuneModCore.Mods
|
||||
}
|
||||
}
|
||||
|
||||
public override Task<string?> Reset()
|
||||
protected override Task<string?> ResetCore()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace ZuneModCore.Mods
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override async Task<string?> Apply()
|
||||
protected override async Task<string?> ApplyCore()
|
||||
{
|
||||
// Verify that ZuneServices.dll exists
|
||||
FileInfo zsDllInfo = new(Path.Combine(ModManager.ZuneInstallDir, "ZuneService.dll"));
|
||||
@@ -183,7 +183,7 @@ namespace ZuneModCore.Mods
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<string?> Reset()
|
||||
protected override async Task<string?> ResetCore()
|
||||
{
|
||||
string zsDllPath = Path.Combine(ModManager.ZuneInstallDir, "ZuneService.dll");
|
||||
try
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Win32;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ZuneModCore.Win32
|
||||
{
|
||||
@@ -7,6 +8,7 @@ namespace ZuneModCore.Win32
|
||||
|
||||
public class RegEdit
|
||||
{
|
||||
public const string HIVE_CURRENTUSER = "HKEY_CURRENT_USER";
|
||||
public const string ZUNE_REG_PATH = @"SOFTWARE\Microsoft\Zune\";
|
||||
|
||||
public static bool CurrentUserSetBoolValue(string key, string name, bool value)
|
||||
@@ -66,6 +68,46 @@ namespace ZuneModCore.Win32
|
||||
|
||||
regKey.DeleteValue(name, false);
|
||||
}
|
||||
|
||||
public static void ExportKey(string hive, string regKey, string savePath, bool overwrite = true)
|
||||
{
|
||||
string path = $"\"{savePath}\"";
|
||||
string key = $"\"{hive}\\{regKey}\"";
|
||||
|
||||
Process proc = null!;
|
||||
try
|
||||
{
|
||||
string cmd = $"reg export {key} {path}";
|
||||
|
||||
if (overwrite)
|
||||
cmd += " /y";
|
||||
|
||||
proc = Process.Start("cmd.exe", $"/c {cmd}");
|
||||
if (proc != null) proc.WaitForExit();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (proc != null) proc.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ImportKey(string savePath)
|
||||
{
|
||||
string path = "\"" + savePath + "\"";
|
||||
|
||||
Process proc = null!;
|
||||
try
|
||||
{
|
||||
string cmd = $"reg import {path}";
|
||||
|
||||
proc = Process.Start("cmd.exe", $"/c \"{cmd}\"");
|
||||
if (proc != null) proc.WaitForExit();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (proc != null) proc.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore CA1416 // Validate platform compatibility
|
||||
|
||||
@@ -54,10 +54,17 @@ namespace ZuneModdingHelper
|
||||
string zuneExePath = Path.Combine(ModManager.ZuneInstallDir, "Zune.exe");
|
||||
if (procs.Length > 0 && procs.Any(p => p.MainModule.FileName == zuneExePath))
|
||||
{
|
||||
MetroDialogSettings dialogSettings = new()
|
||||
{
|
||||
ColorScheme = MetroDialogColorScheme.Accented,
|
||||
AnimateShow = true,
|
||||
AnimateHide = true,
|
||||
AffirmativeButtonText = "OK"
|
||||
};
|
||||
await this.ShowMessageAsync(
|
||||
"Warning",
|
||||
"The Zune software is currently running. You may run into issues applying or resetting mods.",
|
||||
settings: defaultMetroDialogSettings);
|
||||
settings: dialogSettings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +94,7 @@ namespace ZuneModdingHelper
|
||||
await progDialog.CloseAsync();
|
||||
return;
|
||||
}
|
||||
mod.OptionsUI = (AbstractUICollection)optionsDialog.OptionsViewModel.Model;
|
||||
//mod.OptionsUI = (AbstractUICollection)optionsDialog.ViewModel.Model;
|
||||
}
|
||||
progDialog.SetProgress(++numCompleted);
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
|
||||
mc:Ignorable="d"
|
||||
Title="Options" Height="450" Width="800"
|
||||
WindowStyle="ToolWindow">
|
||||
WindowStyle="ToolWindow"
|
||||
Loaded="Window_Loaded">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
@@ -30,9 +31,9 @@
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Margin="10,10,10,0" Visibility="{Binding CurrentMod.DependentMods, Converter={StaticResource NullToVisibilityConverter}}">
|
||||
<StackPanel Margin="10,10,10,0" Visibility="{Binding ViewModel.HasDependencies}">
|
||||
<TextBlock Text="Dependencies" FontSize="26"/>
|
||||
<ItemsControl x:Name="DependenciesPresenter" ItemsSource="{Binding CurrentMod.DependentMods}">
|
||||
<ItemsControl x:Name="DependenciesPresenter" ItemsSource="{Binding ViewModel.Mod.DependentMods}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type mod:ModDependency}">
|
||||
<TextBlock Margin="4" FontSize="14">
|
||||
@@ -49,8 +50,9 @@
|
||||
Height="2" Margin="0,10,0,-7"/>
|
||||
</StackPanel>
|
||||
|
||||
<absui:AbstractUIGroupPresenter x:Name="OptionsUIPresenter" ViewModel="{Binding OptionsViewModel}"
|
||||
TemplateSelector="{StaticResource GroupTemplateSelector}"/>
|
||||
<absui:AbstractUIGroupPresenter x:Name="OptionsUIPresenter" ViewModel="{Binding ViewModel.OptionsViewModel}"
|
||||
TemplateSelector="{StaticResource GroupTemplateSelector}"
|
||||
Visibility="{Binding ViewModel.HasOptions}"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
@@ -80,7 +82,8 @@
|
||||
<Button x:Name="OptionsUICancelButton" Content="Cancel" Click="OptionsUICancelButton_Click"
|
||||
Grid.Column="1" Style="{StaticResource SecondaryButton}"/>
|
||||
|
||||
<Button x:Name="OptionsUINextButton" Content="Next" Click="OptionsUINextButton_Click"
|
||||
<Button x:Name="OptionsUINextButton" Content="{Binding ViewModel.ActionButtonText}"
|
||||
Command="{Binding ViewModel.ActionCommand}"
|
||||
Grid.Column="2" Style="{StaticResource PrimaryButton}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
@@ -17,13 +17,9 @@ namespace ZuneModdingHelper
|
||||
InitializeComponent();
|
||||
|
||||
DataContext = this;
|
||||
CurrentMod = mod;
|
||||
if (CurrentMod.OptionsUI != null)
|
||||
{
|
||||
OptionsViewModel = new(CurrentMod.OptionsUI);
|
||||
}
|
||||
ViewModel = new(mod);
|
||||
|
||||
Title = "Options | " + CurrentMod.Title;
|
||||
Title = "Options | " + ViewModel.Mod.Title;
|
||||
}
|
||||
|
||||
private void OptionsUINextButton_Click(object sender, RoutedEventArgs e) => Finish(true);
|
||||
@@ -36,22 +32,17 @@ namespace ZuneModdingHelper
|
||||
Close();
|
||||
}
|
||||
|
||||
public Mod CurrentMod
|
||||
public ModViewModel ViewModel
|
||||
{
|
||||
get => (Mod)GetValue(CurrentModProperty);
|
||||
set => SetValue(CurrentModProperty, value);
|
||||
get => (ModViewModel)GetValue(ViewModelProperty);
|
||||
set => SetValue(ViewModelProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty CurrentModProperty = DependencyProperty.Register(
|
||||
nameof(CurrentMod), typeof(Mod), typeof(OptionsUIDialog));
|
||||
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
|
||||
nameof(ViewModel), typeof(ModViewModel), typeof(OptionsUIDialog));
|
||||
|
||||
public AbstractUICollectionViewModel OptionsViewModel
|
||||
private async void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
get => (AbstractUICollectionViewModel)GetValue(OptionsViewModelProperty);
|
||||
set => SetValue(OptionsViewModelProperty, value);
|
||||
await ViewModel.LoadAsync();
|
||||
}
|
||||
public static readonly DependencyProperty OptionsViewModelProperty = DependencyProperty.Register(
|
||||
nameof(OptionsViewModel), typeof(AbstractUICollectionViewModel), typeof(OptionsUIDialog));
|
||||
|
||||
public bool HasOptions => CurrentMod.OptionsUI != null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user