mirror of
https://github.com/icsharpcode/ILSpy.git
synced 2026-10-12 02:15:58 +00:00
Refactor OptionsDialog to use MVVM style
This commit is contained in:
@@ -26,7 +26,7 @@ using ICSharpCode.ILSpyX.Settings;
|
||||
|
||||
namespace ICSharpCode.ILSpy.ReadyToRun
|
||||
{
|
||||
[ExportOptionPage(Title = nameof(global::ILSpy.ReadyToRun.Properties.Resources.ReadyToRun), Order = 40)]
|
||||
[ExportOptionPage(Order = 40)]
|
||||
[PartCreationPolicy(CreationPolicy.NonShared)]
|
||||
partial class ReadyToRunOptionPage : UserControl, IOptionPage
|
||||
{
|
||||
@@ -35,6 +35,8 @@ namespace ICSharpCode.ILSpy.ReadyToRun
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public string Title => global::ILSpy.ReadyToRun.Properties.Resources.ReadyToRun;
|
||||
|
||||
public void Load(ILSpySettings settings)
|
||||
{
|
||||
Options s = new Options();
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace ICSharpCode.ILSpy.Options
|
||||
/// <summary>
|
||||
/// Interaction logic for DecompilerSettingsPanel.xaml
|
||||
/// </summary>
|
||||
[ExportOptionPage(Title = nameof(Properties.Resources.Decompiler), Order = 10)]
|
||||
[ExportOptionPage(Order = 10)]
|
||||
[PartCreationPolicy(CreationPolicy.NonShared)]
|
||||
internal partial class DecompilerSettingsPanel : IOptionPage
|
||||
{
|
||||
@@ -35,6 +35,8 @@ namespace ICSharpCode.ILSpy.Options
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public string Title => Properties.Resources.Decompiler;
|
||||
|
||||
public static Decompiler.DecompilerSettings LoadDecompilerSettings(ILSpySettings settings)
|
||||
{
|
||||
return ISettingsProvider.LoadDecompilerSettings(settings);
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.Options
|
||||
/// <summary>
|
||||
/// Interaction logic for DisplaySettingsPanel.xaml
|
||||
/// </summary>
|
||||
[ExportOptionPage(Title = nameof(Properties.Resources.Display), Order = 20)]
|
||||
[ExportOptionPage(Order = 20)]
|
||||
[PartCreationPolicy(CreationPolicy.NonShared)]
|
||||
public partial class DisplaySettingsPanel : UserControl, IOptionPage
|
||||
{
|
||||
@@ -67,6 +67,8 @@ namespace ICSharpCode.ILSpy.Options
|
||||
);
|
||||
}
|
||||
|
||||
public string Title => Properties.Resources.Display;
|
||||
|
||||
public void Load(ILSpySettings settings)
|
||||
{
|
||||
this.DataContext = LoadDisplaySettings(settings);
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpy.Options
|
||||
/// <summary>
|
||||
/// Interaction logic for MiscSettingsPanel.xaml
|
||||
/// </summary>
|
||||
[ExportOptionPage(Title = nameof(Properties.Resources.Misc), Order = 30)]
|
||||
[ExportOptionPage(Order = 30)]
|
||||
[PartCreationPolicy(CreationPolicy.NonShared)]
|
||||
public partial class MiscSettingsPanel : UserControl, IOptionPage
|
||||
{
|
||||
@@ -36,6 +36,8 @@ namespace ICSharpCode.ILSpy.Options
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public string Title => Properties.Resources.Misc;
|
||||
|
||||
public void Load(ILSpySettings settings)
|
||||
{
|
||||
this.DataContext = new MiscSettingsViewModel(SettingsService.Instance.MiscSettings);
|
||||
|
||||
@@ -1,35 +1,43 @@
|
||||
<Window x:Class="ICSharpCode.ILSpy.Options.OptionsDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
|
||||
xmlns:options="clr-namespace:ICSharpCode.ILSpy.Options"
|
||||
Style="{DynamicResource DialogWindow}"
|
||||
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
|
||||
xmlns:options="clr-namespace:ICSharpCode.ILSpy.Options"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:toms="urn:TomsToolbox"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance options:OptionsDialogViewModel}"
|
||||
Style="{StaticResource DialogWindow}"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
ResizeMode="CanResizeWithGrip"
|
||||
Title="{x:Static properties:Resources.Options}" Height="500" Width="600">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition
|
||||
Height="1*" />
|
||||
<RowDefinition
|
||||
Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TabControl Name="tabControl" SelectedValuePath="Content">
|
||||
<DockPanel>
|
||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="12,8">
|
||||
<Button Margin="2,0"
|
||||
Command="{Binding ResetDefaultsCommand}"
|
||||
Content="{x:Static properties:Resources.ResetToDefaults}" />
|
||||
<Button IsDefault="True" Margin="2,0"
|
||||
toms:Button.DialogResult="true"
|
||||
Command="{Binding CommitCommand}"
|
||||
Content="{x:Static properties:Resources.OK}" />
|
||||
<Button IsCancel="True" Margin="2,0"
|
||||
Content="{x:Static properties:Resources.Cancel}" />
|
||||
</StackPanel>
|
||||
<TabControl ItemsSource="{Binding OptionPages}"
|
||||
SelectedIndex="0"
|
||||
SelectedValuePath="Content"
|
||||
SelectedValue="{Binding SelectedPage}">
|
||||
<TabControl.ItemTemplate>
|
||||
<DataTemplate DataType="options:TabItemViewModel">
|
||||
<TextBlock Text="{Binding Header}" />
|
||||
<DataTemplate DataType="options:OptionsItemViewModel">
|
||||
<TextBlock Text="{Binding Title}" />
|
||||
</DataTemplate>
|
||||
</TabControl.ItemTemplate>
|
||||
<TabControl.ContentTemplate>
|
||||
<DataTemplate DataType="options:TabItemViewModel">
|
||||
<DataTemplate DataType="options:OptionsItemViewModel">
|
||||
<ContentPresenter Content="{Binding Content}" />
|
||||
</DataTemplate>
|
||||
</TabControl.ContentTemplate>
|
||||
</TabControl>
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="12,8">
|
||||
<Button Margin="2,0" Name="defaultsButton" Click="DefaultsButton_Click" Content="{x:Static properties:Resources.ResetToDefaults}" />
|
||||
<Button IsDefault="True" Margin="2,0" Name="okButton" Click="OKButton_Click" Content="{x:Static properties:Resources.OK}" />
|
||||
<Button IsCancel="True" Margin="2,0" Content="{x:Static properties:Resources.Cancel}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -18,103 +18,42 @@
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using ICSharpCode.ILSpy.Properties;
|
||||
using ICSharpCode.ILSpyX.Settings;
|
||||
|
||||
using TomsToolbox.Composition;
|
||||
|
||||
namespace ICSharpCode.ILSpy.Options
|
||||
{
|
||||
public class TabItemViewModel
|
||||
{
|
||||
public TabItemViewModel(string header, UIElement content)
|
||||
{
|
||||
Header = header;
|
||||
Content = content;
|
||||
}
|
||||
|
||||
public string Header { get; }
|
||||
|
||||
public UIElement Content { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for OptionsDialog.xaml
|
||||
/// </summary>
|
||||
public partial class OptionsDialog : Window
|
||||
public sealed partial class OptionsDialog
|
||||
{
|
||||
readonly IExport<UIElement, IOptionsMetadata>[] optionPages;
|
||||
|
||||
public OptionsDialog()
|
||||
{
|
||||
DataContext = new OptionsDialogViewModel();
|
||||
InitializeComponent();
|
||||
var ep = App.ExportProvider;
|
||||
this.optionPages = ep.GetExports<UIElement, IOptionsMetadata>("OptionPages").ToArray();
|
||||
ILSpySettings settings = SettingsService.Instance.SpySettings;
|
||||
foreach (var optionPage in optionPages.OrderBy(p => p.Metadata.Order))
|
||||
{
|
||||
var tabItem = new TabItemViewModel(Util.ResourceHelper.GetString(optionPage.Metadata.Title), optionPage.Value);
|
||||
|
||||
tabControl.Items.Add(tabItem);
|
||||
|
||||
IOptionPage page = optionPage.Value as IOptionPage;
|
||||
if (page != null)
|
||||
page.Load(settings);
|
||||
}
|
||||
}
|
||||
|
||||
void OKButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SettingsService.Instance.SpySettings.Update(
|
||||
root => {
|
||||
foreach (var optionPage in optionPages)
|
||||
{
|
||||
IOptionPage page = optionPage.Value as IOptionPage;
|
||||
if (page != null)
|
||||
page.Save(root);
|
||||
}
|
||||
});
|
||||
this.DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void DefaultsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (MessageBox.Show(Properties.Resources.ResetToDefaultsConfirmationMessage, "ILSpy", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
|
||||
{
|
||||
var page = tabControl.SelectedValue as IOptionPage;
|
||||
if (page != null)
|
||||
page.LoadDefaults();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IOptionsMetadata
|
||||
{
|
||||
string Title { get; }
|
||||
int Order { get; }
|
||||
}
|
||||
|
||||
public interface IOptionPage
|
||||
{
|
||||
string Title { get; }
|
||||
void Load(ILSpySettings settings);
|
||||
void Save(XElement root);
|
||||
void LoadDefaults();
|
||||
}
|
||||
|
||||
[MetadataAttribute]
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
public class ExportOptionPageAttribute : ExportAttribute
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class ExportOptionPageAttribute() : ExportAttribute("OptionPages", typeof(IOptionPage)), IOptionsMetadata
|
||||
{
|
||||
public ExportOptionPageAttribute() : base("OptionPages", typeof(UIElement))
|
||||
{ }
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public int Order { get; set; }
|
||||
}
|
||||
|
||||
@@ -125,7 +64,7 @@ namespace ICSharpCode.ILSpy.Options
|
||||
public override void Execute(object parameter)
|
||||
{
|
||||
OptionsDialog dlg = new() {
|
||||
Owner = MainWindow.Instance
|
||||
Owner = MainWindow.Instance,
|
||||
};
|
||||
if (dlg.ShowDialog() == true)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
using TomsToolbox.Essentials;
|
||||
using TomsToolbox.Wpf;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace ICSharpCode.ILSpy.Options
|
||||
{
|
||||
public class OptionsItemViewModel(IOptionPage content) : ObservableObject
|
||||
{
|
||||
public string Title { get; } = content.Title;
|
||||
|
||||
public IOptionPage Content { get; } = content;
|
||||
}
|
||||
|
||||
public class OptionsDialogViewModel : ObservableObject
|
||||
{
|
||||
private IOptionPage? selectedPage;
|
||||
|
||||
private readonly IOptionPage[] optionPages = App.ExportProvider.GetExports<IOptionPage, IOptionsMetadata>("OptionPages")
|
||||
.OrderBy(page => page.Metadata?.Order)
|
||||
.Select(item => item.Value)
|
||||
.ExceptNullItems()
|
||||
.ToArray();
|
||||
|
||||
public OptionsDialogViewModel()
|
||||
{
|
||||
var settings = SettingsService.Instance.SpySettings;
|
||||
|
||||
foreach (var optionPage in optionPages)
|
||||
{
|
||||
optionPage.Load(settings);
|
||||
}
|
||||
|
||||
OptionPages = optionPages.Select(page => new OptionsItemViewModel(page)).ToArray();
|
||||
SelectedPage = optionPages.FirstOrDefault();
|
||||
}
|
||||
|
||||
public OptionsItemViewModel[] OptionPages { get; }
|
||||
|
||||
public IOptionPage? SelectedPage {
|
||||
get => selectedPage;
|
||||
set => SetProperty(ref selectedPage, value);
|
||||
}
|
||||
|
||||
public ICommand CommitCommand => new DelegateCommand(Commit);
|
||||
|
||||
public ICommand ResetDefaultsCommand => new DelegateCommand(ResetDefaults);
|
||||
|
||||
private void ResetDefaults()
|
||||
{
|
||||
if (MessageBox.Show(Properties.Resources.ResetToDefaultsConfirmationMessage, "ILSpy", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
|
||||
{
|
||||
SelectedPage?.LoadDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
private void Commit()
|
||||
{
|
||||
SettingsService.Instance.SpySettings.Update(root => {
|
||||
foreach (var optionPage in optionPages)
|
||||
{
|
||||
optionPage.Save(root);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,12 @@ using System.ComponentModel.Composition;
|
||||
using System.Windows.Controls;
|
||||
using System.Xml.Linq;
|
||||
|
||||
using ICSharpCode.ILSpy;
|
||||
using ICSharpCode.ILSpy.Options;
|
||||
using ICSharpCode.ILSpyX.Settings;
|
||||
|
||||
namespace TestPlugin
|
||||
{
|
||||
[ExportOptionPage(Title = "TestPlugin", Order = 0)]
|
||||
[ExportOptionPage(Order = 0)]
|
||||
[PartCreationPolicy(CreationPolicy.NonShared)]
|
||||
partial class CustomOptionPage : UserControl, IOptionPage
|
||||
{
|
||||
@@ -23,6 +22,8 @@ namespace TestPlugin
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public string Title => "TestPlugin";
|
||||
|
||||
public void Load(ILSpySettings settings)
|
||||
{
|
||||
// For loading options, use ILSpySetting's indexer.
|
||||
|
||||
Reference in New Issue
Block a user