绑定到ObservableCollection的Listbox没有更新

3

我正在使用一个ObservableCollection来存储Windows的环境变量。

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()之后再添加更多的项目到列表中。

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

ListBox 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个回答

3

您没有修改ObservableCollection,只是替换了它。 您应该实现INotifyPropertyChanged并在Variables属性的setter中调用PropertyChanged

顺便说一下,在MVVM实现中为ViewModel拥有一个基类是很常见的:

class VariableViewModel : ViewModelBase

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


抱歉,我不小心编辑了您的帖子!请检查我是否已正确恢复。+1 - HCL
没错,谢谢建议。我会尝试的。 - Mattias Cibien

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

我需要在ListBox属性中添加特定的内容吗? - Mattias Cibien
1
我已经更新了我的答案。你只需要从你的属性设置器中调用OnPropertyChanged事件即可。 - Rohit Vats
还有一件事情,你应该避免为属性设置相同的值,因为这会不必要地引发属性更改事件。这是编写属性的良好实践。 - Rohit Vats
如果VariablesViewModel是您用户控件的数据上下文,则应该在代码后台中的用户控件构造函数中将其设置为数据上下文,而不是在XAML文件中声明为StaticResource。 - Rohit Vats
因为StaticResource是在UI渲染时定义的,这将实例化VariablesViewModel对象,我怀疑您也从代码中显式调用了VariablesViewModel的构造函数,这将为同一类创建两个实例。 - Rohit Vats
显示剩余3条评论

2
问题在于,可能您的VariableModel没有实现INotifyPropertyChanged。通过ObservableCollection,只有对集合的更改才会被报告,而不是包含对象的更改。 在这里您将找到一些实现可能性。

这对我很有帮助,因为从所有的例子中看来,我似乎做得一切都是正确的。当包含对象上的属性更改时,我能够更新ListBox的ItemsSource的唯一方法是在控件/窗口上处理PropertyChanged事件,该事件托管了ListBox。<br/>void item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e){<br/> MyListBox.Refresh();<br/>} - Greg Osborne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接