Equivalent to UserSettings / ApplicationSettings in WPF .NET 5, .NET 6 or .Net Core
Solution 1:
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).
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.
Tested with Visual Studio 1.16.3.5 and a .net core 3.0 WPF project.
Solution 2:
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 ApplicationData
folder, in resemblance to the old 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
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.
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
<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>
Solution 3:
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.
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
.
Here's an example, from the working .Net Standard project:
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; }
}
}
Solution 4:
For Wpf Net.Core
Project click 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
EXAMPLE
Double click 'Settings1.settings' file and Edit
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();
}
Solution 5:
My improvements to the accepted answer were rejected, so here as separate answer.
There is no need for any nuget package and no need to roll your own JSON etc.
By default when creating new .NET Core or .NET5/6 projects the settings section is missing and you have to manually add it.
Just manually create the Properties folder in the solution.
As you name the new folder Properties
you will see that the folder icon will change slightly.
Right click on this new Properties folder and add New Item
Add a Settings File and to be same as in old projects rename the proposed name from Settings1.settings
to Settings.settings
Here you are. Settings are back already.
You might add an Application Configuration File to get the .config file in the output directory