我第一次尝试使用.NET 2.0 ApplicationSettings功能,并且发现它有点......在某些方面令人费解。我希望有人可以帮我弄清楚我哪里出错了。
我有一个通用设置类,我实现了它是ApplicationSettingsBase的子类。我已经实现了一个属性,并对其进行了标记。这似乎有效
然后我尝试将列表框控件绑定到属性,这似乎也有效。当我打开表单时,它会很好地加载属性。
我遇到的问题是,如果我想更新设置和数据绑定而不重新加载表单,它似乎不起作用。没有方法来刷新绑定,从我正在阅读的,它应该只是自动更新(ApplicationSettingsBase实现IPropertyChangeNotify,DataBindings应该订阅..但它似乎没有工作)。如果您有DataBinding,也无法手动更新列表框。
所以这是我的代码:
Settings.cs
public class Settings : ApplicationSettingsBase
{
public Settings()
{
if (FixedBooks == null) FixedBooks = new List<string>();
}
[UserScopedSetting()]
public List<string> FixedBooks
{
get { return (List<string>)this["FixedBooks"]; }
protected set { this["FixedBooks"] = value; }
}
}
SettingsForm.cs
Settings _settings = new Settings();
private void SettingsForm_Load(object sender, EventArgs e)
{
lbFixedColumns.DataBindings.Add(new Binding("DataSource", _settings,
"FixedBooks", false, DataSourceUpdateMode.OnPropertyChanged));
}
private void DoSomething()
{
_settings.FixedBooks.Add("Test");
}
我的理解是,在ApplicationSettings中添加一些内容应该触发IPropertyChangedNotify以警告控件绑定该属性已更改,并强制它重新加载..但这似乎不会发生。
我错过了什么?
编辑:
我相信我知道问题所在。问题是我正在改变Settings类中集合的contentes,但不改变实际属性本身(这是集合本身)。我想我必须实际添加或删除整个集合才能触发IPropertyChangedNotify,这是不会发生的。
我不确定这个问题的解决方案是什么。
答案 0 :(得分:1)
您需要保存设置并重新加载:
private void DoSomething()
{
_settings.FixedBooks.Add("Test");
_settings.Save();
_settings.Reload();
}
我同意您的编辑和评论。请尝试使用BindingList。
public class Settings : ApplicationSettingsBase
{
public Settings()
{
if (FixedBooks == null) FixedBooks = new BindingList<string>();
FixedBooks.ListChanged += FixedBooks_ListChanged;
}
void FixedBooks_ListChanged(object sender, ListChangedEventArgs e)
{
this["FixedBooks"] = FixedBooks;
}
[UserScopedSetting()]
public BindingList<string> FixedBooks
{
get { return (BindingList<string>)this["FixedBooks"]; }
protected set { this["FixedBooks"] = value; }
}
}
答案 1 :(得分:0)
好吧,这不是一个很好的解决方案,而且我希望有人有更好的解决方案,但这有效:
private void DoSomething()
{
_settings.FixedBooks.Add("Test");
var old = _settings.FixedBooks;
_settings["FixedBooks"] = new List<string>();
_settings["FixedBooks"] = old;
}
我尝试简单地重新分配给自己,但显然有一些优化可以检测到这一点并且无法触发PropertyChanged。
我非常乐意回答那些提出更好解决方案的人。
编辑:
好吧,我认为我找到了一个可接受的解决方案,这只是一个小小的问题,并且不需要像上面那样无缘无故地创建新对象。
好的,首先,我在Settings类中添加了一个新方法:
public void FirePropertyChanged(string propertyName)
{
PropertyChangedEventArgs args2 = new PropertyChangedEventArgs(propertyName);
OnPropertyChanged(this, args2);
}
这允许我触发PropertyChanged事件而不实际更改属性。但是,Binding类对我来说仍然有点太聪明,因为它知道该属性实际上没有改变..所以它什么也没做。
private void DoSomething()
{
_settings.FixedBooks.Add("Test");
lbFixedColumns.DataSource = null;
_settings.FirePropertyChanged("FixedBooks");
}
因此,这段代码伪造了Binding类,通过清除DataSource,它现在无法判断该属性是否已更改,因此它必须提取最新版本的数据。我可以忍受这个,即使它仍然有点臭。
EDIT2:
正如drs指出的那样,我应该使用BindingList而不是List,使用BindingList是正确的解决方案。