2009-07-24 6 views
1

J'essaie d'utiliser la fonction .NET 2.0 ApplicationSettings pour la première fois, et je trouve ça un peu ... déroutant à certains égards. J'espère que quelqu'un pourra m'aider à comprendre où je me trompe.Mise à jour des contrôles liés à ApplicationSettings

J'ai une classe de paramètres génériques que j'ai implémentée qui est une sous-classe de ApplicationSettingsBase. J'ai implémenté une propriété et l'ai taguée. Cela semble fonctionner

J'ai ensuite essayé de lier un contrôle de zone de liste à la propriété, et cela semble également fonctionner. Lorsque j'ouvre le formulaire, il charge les propriétés très bien.

Le problème que je rencontre est que si je veux mettre à jour les paramètres et la liaison de données sans recharger le formulaire, cela ne semble pas fonctionner. Il n'y a pas de méthodes pour actualiser la liaison, et d'après ce que je lis, elle devrait juste mettre à jour automatiquement (ApplicationSettingsBase implémente IPropertyChangeNotify, auquel DataBindings devrait s'abonner ... mais cela ne semble pas fonctionner). Vous ne pouvez pas non plus mettre à jour manuellement la zone de liste si vous avez un DataBinding.

Alors, voici mon code:

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"); 
} 

Ma compréhension est que l'ajout de quelque chose aux ApplicationSettings devrait tirer le IPropertyChangedNotify pour alerter le contrôle liant que la propriété a changé, et le forcer à recharger .. mais cela ne semble pas se produire.

Qu'est-ce qui me manque?

EDIT:

Je crois que je sais ce que le problème est. Le problème est que je modifie les contentes de la collection dans la classe Settings, mais ne change pas la propriété elle-même (qui est la collection elle-même). Je pense que je devrais réellement ajouter ou enlever la collection entière pour obtenir le IPropertyChangedNotify pour tirer, qui ne se produit pas.

Je ne suis pas sûr de la solution à ce problème.

Répondre

1

Vous devez enregistrer le réglage et le recharger:

private void DoSomething() 
{ 
    _settings.FixedBooks.Add("Test"); 
    _settings.Save(); 
    _settings.Reload(); 
} 

Je suis d'accord avec votre éditer et votre commentaire. Essayez d'utiliser une BindingList à la place.

Exemple:

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; } 
    } 
} 
+0

Ce n'est pas une bonne option, car elle détruit la possibilité d'annuler sans enregistrer les paramètres. Je veux seulement appeler Save() quand j'appuie sur Appliquer ou OK. –

+0

Doh! C'est l'un des problèmes avec .NET, il est tellement énorme que parfois vous ne pouvez pas trouver ce genre de choses ... 4 heures à venir avec des solutions de rechange dans les toilettes avec la solution que cela est conçu pour ... –

0

Ok, pas une bonne solution, et j'espère que quelqu'un a une meilleure, mais cela fonctionne:

private void DoSomething() 
{ 
    _settings.FixedBooks.Add("Test");  
    var old = _settings.FixedBooks; 
    _settings["FixedBooks"] = new List<string>(); 
    _settings["FixedBooks"] = old; 
} 

J'ai essayé de simplement se réaffectant à lui-même, mais il y a apparemment une optimisation là-dedans qui détecte cela et ne parvient pas à déclencher le PropertyChanged.

Je serais plus qu'heureux de répondre à quelqu'un qui trouverait une meilleure solution.

EDIT:

Ok, je pense avoir trouvé une solution acceptable qui est seulement un peu kludgey, et ne nécessite pas la création de nouveaux objets comme ci-dessus sans raison.

Ok, d'abord, ajouter une nouvelle méthode pour ma classe Paramètres:

public void FirePropertyChanged(string propertyName) 
{ 
    PropertyChangedEventArgs args2 = new PropertyChangedEventArgs(propertyName); 
    OnPropertyChanged(this, args2); 
} 

Cela me permet de déclencher un événement PropertyChanged sans changer la propriété. Cependant, la classe Binding est encore un peu trop intelligente pour moi, car elle sait que la propriété n'a pas vraiment changé ... donc ça ne fait rien.

private void DoSomething() 
{ 
    _settings.FixedBooks.Add("Test"); 
    lbFixedColumns.DataSource = null; 
    _settings.FirePropertyChanged("FixedBooks"); 
} 

Ainsi, ce code Fakes la classe Binding, en effaçant le DataSource il maintenant ne peut pas dire que la propriété n'a pas changé, il doit tirer la dernière version des données. Je peux vivre avec ça, même si c'est encore un peu puant.

EDIT2:

Comme drs souligne, j'aurais utilisé un BindingList plutôt que d'une liste, en utilisant une BindingList est la bonne solution.