将绑定控件更新到ApplicationSettings

时间:2009-07-24 01:17:24

标签: c# data-binding .net-2.0 settings

我第一次尝试使用.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,这是不会发生的。

我不确定这个问题的解决方案是什么。

2 个答案:

答案 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是正确的解决方案。