What is the prefered way for persisting user settings for WPF applications with .NET 5, .NET 6 or .Net Core >=3.0?
Where are the .NET user settings gone?
Created WPF .Net Core 3.0 Project (VS2019 V16.3.1) Now I have seen there is no Properties.Settings section anymore. [Update 2022: With .NET 6 it is still the same]
After online search, started to dive into Microsoft.Extensions.Configuration.
Beside the bloated code to access the settings, now even worse -> No save?
User Configuration Settings in .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?
add the variables to the Properties.
Read the variables at startupvar culture = new CultureInfo(Properties.Settings.Default.LanguageSettings);
when a variable changes -> immediately save itProperties.Settings.Default.LanguageSettings = selected.TwoLetterISOLanguageName; Properties.Settings.Default.Save();
The . NET Upgrade Assistant is a command-line tool that can assist with upgrading . NET Framework WPF apps to . NET 6.
It has support for all kinds of . NET applications, including the Windows desktop platforms such as WPF, Windows Forms, and WinUI 3.0.
No. A WPF application targeting . NET Framework cannot reference a . NET Core project.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With