相当于 WPF dotnet core 中的 UserSettings / ApplicationSettings

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/56847571/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 14:11:27  来源:igfitidea点击:

Equivalent to UserSettings / ApplicationSettings in WPF dotnet core

c#wpf.net-core

提问by MarkusEgle

What is the prefered way for persisting user settings for WPF applications with .Net Core >=3.0?

使用 .Net Core >=3.0 为 WPF 应用程序保留用户设置的首选方法是什么?

Created WPF .Net Core 3.0 Project (VS2019 V16.3.1) Now I have seen there is no Properties.Settings section anymore.

创建了 WPF .Net Core 3.0 项目 (VS2019 V16.3.1) 现在我看到没有 Properties.Settings 部分了。

SolutionExplorer

解决方案浏览器

After online search, started to dive into Microsoft.Extensions.Configuration.

网上搜索后,开始潜入Microsoft.Extensions.Configuration。

Beside the bloated code to access the settings, now even worse -> No save?
User Configuration Settings in .NET Core

除了访问设置的臃肿代码,现在更糟 -> 没有保存?
.NET Core 中的用户配置设置

Fortunately or unfortunately the Microsoft.Extensions.Configuration does not support saving by design. Read more in this Github issue Why there is no save in ConfigurationProvider?

幸运或不幸的是,Microsoft.Extensions.Configuration 不支持按设计保存。在此 Github 问题中阅读更多信息为什么 ConfigurationProvider 中没有保存?


What is the prefered (and easy/fast/simple) way for persisting user settings for WPF applications with .Net Core >=3.0?


使用 .Net Core >=3.0 为 WPF 应用程序保留用户设置的首选(和简单/快速/简单)方法是什么?


Before <= .Net 4.8it was as easy as:


之前<= .Net 4.8它很简单:

  • add the variables to the Properties. User Settings

  • Read the variables at startup
    var culture = new CultureInfo(Properties.Settings.Default.LanguageSettings);

  • when a variable changes -> immediately save it
    Properties.Settings.Default.LanguageSettings = selected.TwoLetterISOLanguageName; Properties.Settings.Default.Save();

  • 将变量添加到属性。 用户设置

  • 启动时读取变量
    var culture = new CultureInfo(Properties.Settings.Default.LanguageSettings);

  • 当变量改变时 -> 立即保存
    Properties.Settings.Default.LanguageSettings = selected.TwoLetterISOLanguageName; Properties.Settings.Default.Save();

采纳答案by Alexander Zwitbaum

enter image description here

在此处输入图片说明

You can add the same old good settings file e.g. via the right click on the Properties -> Add -> New Item and search for the "Settings". The file can be edited in the settings designer and used as in the .net framework projects before (ConfigurationManager, Settings.Default.Upgrade(), Settings.Default.Save, etc. works).

您可以添加相同的旧设置文件,例如通过右键单击“属性”->“添加”->“新项目”并搜索“设置”。该文件可以在设置设计器中编辑,并在之前的 .net 框架项目中使用(ConfigurationManager、Settings.Default.Upgrade()、Settings.Default.Save 等工作)。

Add also the app.config file to the project root folder (the same way via the Add -> New Item), save the settings once again, compile the project and you will find a .dll.config file in the output folder. You can change now default app values as before.

还将 app.config 文件添加到项目根文件夹(通过添加 -> 新项目的方式相同),再次保存设置,编译项目,您将在输出文件夹中找到一个 .dll.config 文件。您现在可以像以前一样更改默认应用程序值。

Tested with Visual Studio 1.16.3.5 and a .net core 3.0 WPF project.

使用 Visual Studio 1.16.3.5 和 .net core 3.0 WPF 项目进行测试。

回答by Funk

As pointed out in the posts you referenced, the Microsoft.Extensions.Configuration API is meant as a one time set up for your app, or at the very least to be read-only. If you're main goal is to persist user settings easy/fast/simple, you could roll something up yourself. Storing the settings in the ApplicationDatafolder, in resemblance to the old API.

正如您在引用的帖子中指出的那样,Microsoft.Extensions.Configuration API 旨在为您的应用程序一次性设置,或者至少是只读的。如果您的主要目标是轻松/快速/简单地保留用户设置,那么您可以自己动手做一些事情。将设置存储在ApplicationData文件夹中,类似于旧 API。

public class SettingsManager<T> where T : class
{
    private readonly string _filePath;

    public SettingsManager(string fileName)
    {
        _filePath = GetLocalFilePath(fileName);
    }

    private string GetLocalFilePath(string fileName)
    {
        string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
        return Path.Combine(appData, fileName);
    }

    public T LoadSettings() =>
        File.Exists(_filePath) ?
        JsonConvert.DeserializeObject<T>(File.ReadAllText(_filePath)) :
        null;

    public void SaveSettings(T settings)
    {
        string json = JsonConvert.SerializeObject(settings);
        File.WriteAllText(_filePath, json);
    }
}


A demo using the most basic of UserSettings

使用最基本的演示 UserSettings

public class UserSettings
{
    public string Name { get; set; }
}

I'm not going to provide a full MVVM example, still we'd have an instance in memory, ref _userSettings. Once you load settings, the demo will have its default properties overridden. In production, of course, you wouldn't provide default values on start up. It's just for the purpose of illustration.

我不会提供完整的 MVVM 示例,但我们仍然在内存中有一个实例 ref _userSettings。加载设置后,演示将覆盖其默认属性。当然,在生产中,您不会在启动时提供默认值。这只是为了说明的目的。

public partial class MainWindow : Window
{
    private readonly SettingsManager<UserSettings> _settingsManager;
    private UserSettings _userSettings;

    public MainWindow()
    {
        InitializeComponent();

        _userSettings = new UserSettings() { Name = "Funk" };
        _settingsManager = new SettingsManager<UserSettings>("UserSettings.json");
    }

    private void Button_FromMemory(object sender, RoutedEventArgs e)
    {
        Apply(_userSettings);
    }

    private void Button_LoadSettings(object sender, RoutedEventArgs e)
    {
        _userSettings = _settingsManager.LoadSettings();
        Apply(_userSettings);
    }

    private void Button_SaveSettings(object sender, RoutedEventArgs e)
    {
        _userSettings.Name = textBox.Text;
        _settingsManager.SaveSettings(_userSettings);
    }

    private void Apply(UserSettings userSettings)
    {
        textBox.Text = userSettings?.Name ?? "No settings found";
    }
}

XAML

XAML

<Window x:Class="WpfApp.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:WpfApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="Button">
            <Setter Property="Margin" Value="10"/>
        </Style> 
    </Window.Resources>
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" x:Name="textBox" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Button Grid.Row="1" Click="Button_FromMemory">From Memory</Button>
        <Button Grid.Row="2" Click="Button_LoadSettings">Load Settings</Button>
        <Button Grid.Row="3" Click="Button_SaveSettings">Save Settings</Button>
    </Grid>
</Window>

回答by Tom

You can use a Nuget package System.Configuration.ConfigurationManager. It is compatible with .Net Standard 2.0, so it should be usable in .Net Core application.

您可以使用 Nuget 包System.Configuration.ConfigurationManager。它与 .Net Standard 2.0 兼容,因此应该可以在 .Net Core 应用程序中使用。

There is no designer for this, but otherwise it works the same as .Net version, and you should be able to just copy the code from your Settings.Designer.cs. Also, you can override OnPropertyChanged, so there's no need to call Save.

没有为此设计器,但除此之外它的工作方式与 .Net 版本相同,您应该能够从Settings.Designer.cs. 此外,您可以覆盖OnPropertyChanged,因此无需调用Save.

Here's an example, from the working .Net Standard project:

这是一个来自正在运行的 .Net Standard 项目的示例:

public class WatchConfig: ApplicationSettingsBase
{
    static WatchConfig _defaultInstance = (WatchConfig)Synchronized(new WatchConfig());

    public static WatchConfig Default { get => _defaultInstance; }

    protected override void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Save();
        base.OnPropertyChanged(sender, e);
    }

    [UserScopedSetting]
    [global::System.Configuration.DefaultSettingValueAttribute(
    @"<?xml    version=""1.0"" encoding=""utf-16""?>
    <ArrayOfString>
      <string>C:\temp</string>
     <string>..\otherdir</string>
     </ArrayOfString>")]
    public StringCollection Directories
    {
        get { return (StringCollection)this[nameof(Directories)]; }
        set { this[nameof(Directories)] = value; }
    }
}

回答by mdimai666

For Wpf Net.Core

对于 Wpf Net.Core

Projectclick Right Mouse Button -> Add New Item -> Settings File (General)

项目单击鼠标右键 -> 添加新项目 -> 设置文件(常规)

Use

Settings1.Default.Height = this.Height;
Settings1.Default.Width = this.Width;

this.Height = Settings1.Default.Height;
this.Width = Settings1.Default.Width;

Settings1.Default.Save();

Where 'Settings1' created file name

'Settings1' 创建的文件名

EXAMPLE

例子

Double click 'Settings1.settings' file and Edit

双击“ Settings1.settings”文件并编辑

private void MainWindowRoot_SourceInitialized(object sender, EventArgs e)
{
    this.Top = Settings1.Default.Top;
    this.Left = Settings1.Default.Left;
    this.Height = Settings1.Default.Height;
    this.Width = Settings1.Default.Width;
    // Very quick and dirty - but it does the job
    if (Settings1.Default.Maximized)
    {
        WindowState = WindowState.Maximized;
    }
}

private void MainWindowRoot_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    if (WindowState == WindowState.Maximized)
    {
        // Use the RestoreBounds as the current values will be 0, 0 and the size of the screen
        Settings1.Default.Top = RestoreBounds.Top;
        Settings1.Default.Left = RestoreBounds.Left;
        Settings1.Default.Height = RestoreBounds.Height;
        Settings1.Default.Width = RestoreBounds.Width;
        Settings1.Default.Maximized = true;
    }
    else
    {
        Settings1.Default.Top = this.Top;
        Settings1.Default.Left = this.Left;
        Settings1.Default.Height = this.Height;
        Settings1.Default.Width = this.Width;
        Settings1.Default.Maximized = false;
    }

    Settings1.Default.Save();
}

回答by Danny McNaught

Just double click the Settings.settingsfile in your project. It will still open up in the designer just like before. You just do not have it listed in Properties windows anymore.

只需双击Settings.settings项目中的文件。它仍然会像以前一样在设计器中打开。您只是不再在“属性”窗口中列出它。