【问题标题】:Updating bound controls to ApplicationSettings将绑定控件更新到 ApplicationSettings
【发布时间】:2009-07-24 01:17:24
【问题描述】:

我第一次尝试使用 .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 以提醒控件绑定该属性已更改,并强制它重新加载..但这似乎没有发生。

我错过了什么?

编辑:

我相信我知道问题出在哪里。问题是我正在更改设置类中集合的内容,但没有更改实际属性本身(即集合本身)。我想我必须实际添加或删除整个集合才能让 IPropertyChangedNotify 触发,这不会发生。

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

【问题讨论】:

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


    【解决方案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; }
        }
    }
    

    【讨论】:

    • 这不是一个好的选择,因为它破坏了在不保存设置的情况下取消的能力。我只想在点击 Apply 或 OK 时调用 Save()。
    • 噢!这是 .NET 的问题之一,它是如此之大,以至于有时您根本找不到这些东西……花了 4 个小时在厕所里想出解决方法,并为此设计了解决方案……
    【解决方案2】:

    好吧,这不是一个很好的解决方案,我希望有人有更好的解决方案,但这很有效:

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

    【讨论】:

      猜你喜欢
      • 2010-09-09
      • 1970-01-01
      • 2013-07-25
      • 1970-01-01
      • 2010-09-06
      • 1970-01-01
      • 2012-07-11
      • 2021-11-22
      • 2023-03-26
      相关资源
      最近更新 更多