2011-04-30 17 views
3

ObservableCollectionを使用してWindowsの環境変数を保存しています。ObservableCollectionにバインドされたリストボックスは更新されません

class VariableVieWModel 
{ 
    ObservableCollection<VariableModel> vars; 

    public ObservableCollection<VariableModel> Variables 
    { 
     get 
     { 
      return vars; 
     } 
     set 
     { 
      vars = value; 
     } 
    } 

    public VariableViewModel() 
    { 
     Reload(); 
    } 

    public void Reload() 
    { 
    // Code to retrieve vars 
    } 
} 

このObservableCollectionは、ListBoxにバインドされています。

GUIにボタンを追加して、変数をリロードしました。クリックすると、Reload()プロシージャが呼び出されます。

リストボックスの内容は変更されず、Reload()を呼び出すリストにアイテムを追加することはできません。

コンストラクタの下ですべて正常に動作しています。

のListBox XAML:

<ListBox x:Name="lbVariables" Grid.Column="0" Margin="0,0,5,0" ItemsSource="{Binding Source={StaticResource variablesViewModel}, Path=Variables}" IsSynchronizedWithCurrentItem="True"> 

私はまた、UpdateSourceトリガーとしてのPropertyChangedとモードのほとんどを設定し使用してみました。

public void Reload() 
    { 
     vars = new ObservableCollection<VariableModel>(); 

     RegistryKey systemVarKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment"); 

     string[] systemVars = systemVarKey.GetValueNames(); 

     foreach (string var in systemVars) 
     { 
      vars.Add(new VariableModel() 
      { 
       Name = var, 
       Values = (systemVarKey.GetValue(var, null, RegistryValueOptions.DoNotExpandEnvironmentNames) as string).Split(';').ToList<string>(), 
       Target = EnvironmentVariableTarget.Machine 
      }); 
     } 
     systemVarKey.Close(); 

     RegistryKey userVarKey = Registry.CurrentUser.OpenSubKey(@"Environment"); 

     string[] userVars = userVarKey.GetValueNames(); 

     foreach (string var in userVars) 
     { 
      vars.Add(new VariableModel() 
      { 
       Name = var, 
       Values = (userVarKey.GetValue(var, null, RegistryValueOptions.DoNotExpandEnvironmentNames) as string).Split(';').ToList<string>(), 
       Target = EnvironmentVariableTarget.User 
      }); 
     } 
     userVarKey.Close(); 
    } 

答えて

3

VariableVieWModelにターゲットオブジェクトバインディングをリフレッシュするためにINotifyPropertyChangedを実装する必要があります。あなたはちょうどこのようにする必要があります -

class VariableVieWModel : INotifyPropertyChanged 
    { . 
     . 
      public ObservableCollection<VariableModel> Variables 
      { 
       get 
       { 
        return vars; 
       } 
       set 
       { 
        if(vars!=value) 
        { 
         vars = value; 
         OnPropertyChanged("Variables"); 
        } 
       } 
      } 

      public event PropertyChangedEventHandler PropertyChanged;  
      protected void OnPropertyChanged(string name) 
      { 
       PropertyChangedEventHandler handler = PropertyChanged; 
       if (handler != null) 
       { 
        handler(this, new PropertyChangedEventArgs(name)); 
       } 
      } 
    } 
+0

特にListBoxのプロパティに何かを追加する必要がありますか? –

+0

私は自分の答えを更新しました。あなたはあなたのプロパティセッターからOnPropertyChangedイベントを呼び出す必要があります。 –

+0

もう1つのことは、不必要にプロパティー変更イベントを発生させるため、プロパティーに同じ値を設定しないでください。プロパティを書くための良い習慣です。 –

3

ObservableCollectionを変更しておらず、置き換えただけです。 INotifyPropertyChangedを実装し、プロパティセッターでPropertyChangedを呼び出してください。

class VariableViewModel : ViewModelBase 

とコードの重複を避けるために、このような基本クラスでINotifyPropertyChangedなどの一般的な機能を実装:

ところで、それはあなたのViewModelの基本クラスを持つようにMVVM実装で一般的です。

+0

+1申し訳ありませんが、あなたの投稿を誤って編集しました!私がそれを修復したかどうか見てください。 – HCL

+0

それはcorrenctです...提案に感謝します。私は試してみるよ。 –

2

問題は、VariableModelがINotifyPropertyChangedを実装していない可能性があるということです。 ObservableCollectionを使用すると、コレクションの変更のみが報告され、含まれるオブジェクトの変更は報告されません。

Hereいくつかの実装方法があります。

+0

これは、すべての事例から、すべてのことを正しくやっているように感じました。含まれているオブジェクトのプロパティが変更されたときにListBoxのItemsSourceを取得できる唯一の方法は、ListBoxをホストするコントロール/ウィンドウのPropertyChangedイベントをハンドリングすることでした。

void item_PropertyChanged(Object sender、System.ComponentModel.PropertyChangedEventArgs e) {
MyListBox.Refresh();
} –

関連する問題