I have the following:
MainWindow:
<Window x:Class="TestApp.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:TestApp"
xmlns:settings="clr-namespace:TestApp.Settings"
mc:Ignorable="d" Title="MainWindow" Height="350" Width="525">
<Grid>
<ItemsControl>
<ItemsControl.ItemsSource>
<Binding>
<Binding.Source>
<CollectionViewSource Source="{Binding Source={x:Static settings:CustomSettings.Default}, Path=coll}" />
</Binding.Source>
</Binding>
</ItemsControl.ItemsSource>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Name}" />
<Button Grid.Column="1" Click="Button_Click" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
Code-Behind:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace TestApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
if (Settings.CustomSettings.Default.coll == null)
{
Settings.CustomSettings.Default.coll = new ObservableCollection<BasicClass>();
Settings.CustomSettings.Default.coll.Add(new BasicClass("String1"));
Settings.CustomSettings.Default.coll.Add(new BasicClass("String2"));
Settings.CustomSettings.Default.coll.Add(new BasicClass("String3"));
}
Settings.CustomSettings.Default.Save();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Settings.CustomSettings.Default.Save();
foreach (BasicClass item in Settings.CustomSettings.Default.coll)
{
MessageBox.Show(item.Name);
}
}
}
public class BasicClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private string name;
public string Name
{
get { return name; }
set
{
if (value != name)
{
name = value;
NotifyPropertyChanged("Name");
}
}
}
public BasicClass() { }
public BasicClass(string Name)
{
this.Name = Name;
}
}
}
Settings:
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
namespace TestApp.Settings
{
internal sealed partial class CustomSettings : ApplicationSettingsBase
{
private static CustomSettings defaultInstance = ((CustomSettings)(Synchronized(new CustomSettings())));
public static CustomSettings Default
{
get
{
return defaultInstance;
}
}
[UserScopedSetting()]
[DebuggerNonUserCode()]
public ObservableCollection<BasicClass> coll
{
get
{
return ((ObservableCollection<BasicClass>)(this["coll"]));
}
set
{
this["coll"] = value;
}
}
}
}
How it works:
The app present three controls consisting of a TextBox
and a Button
. These are part of an ItemsControl
whose source is bound to a user setting 'coll', of type ObservableCollection<BasicClass>
. BasicClass
has one property, 'Name', which appears in the TextBox
via data-binding.
Expected behaviour:
I change the text in a TextBox
, then click the corresponding Button
. This would then save the new value in 'coll', and then present a MessageBox
sequence demonstrating that this has indeed been changed. I restart the app, and my value is showing the newly saved value.
Actual behaviour:
I change the text, I click the Button
, the MessageBox
sequence shows me that the value is now stored in the user settings (and should therefore have been saved). However, when I restart the app, I see the original value, not the saved one.
An anomaly(?):
If I click the button twice instead of once (going through the MessageBox
sequence twice), when I restart the value has now been successfully saved.