2011-04-30 79 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()过程。

但是,ListBox内容不会改变,我无法再向列表调用Reload()添加项目。

在构造函数下一切工作正常。

列表框XAML:

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

我试着用同样的PropertyChanged为UpdateSource触发,并设置大多数模式。

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属性? – 2011-04-30 12:17:37

+0

我已经更新了我的答案。你只需要从属性设置器中调用OnPropertyChanged事件。 – 2011-04-30 12:18:50

+0

还有一件事你应该避免为财产设置相同的值,因为它会不必要地提高财产变更事件。写作财产只是一个好习惯。 – 2011-04-30 12:20:34

3

您尚未修改ObservableCollection,只替换它。 您应该执行INotifyPropertyChanged并在Variables属性设置器中调用PropertyChanged

BTW这是常见的MVVM的实现有一个基类为您的视图模型:

class VariableViewModel : ViewModelBase 

,并在基类中实现常见的功能,比如INotifyPropertyChanged,以避免重复代码。

+0

+1对不起,我不小心编辑了你的帖子!请看看我是否已经恢复它正确。 – HCL 2011-04-30 11:39:46

+0

这是有道理的......感谢您的建议。我会试一试。 – 2011-04-30 12:01:14

2

问题是,可能你的VariableModel没有实现INotifyPropertyChanged。通过ObservableCollection,只会报告集合的更改,而不会更改包含的对象。

Here你会发现一些实现的可能性。

+0

这帮助我从所有例子中,我似乎做的一切都是正确的。当包含对象上的属性发生更改时,我可以使ListBox的ItemsSource更新的唯一方法是处理托管ListBox的控件/窗口上的PropertyChanged事件。void item_PropertyChanged(object sender,System.ComponentModel.PropertyChangedEventArgs e) {
MyListBox.Refresh();
} – 2014-10-08 17:33:18

相关问题