如何刷新ItemsSource绑定?

11

我有一个视图,其中显示了绑定到 GetAll() 的列表框:

<DockPanel>
    <ListBox ItemsSource="{Binding GetAll}"
             ItemTemplate="{StaticResource allCustomersDataTemplate}"
             Style="{StaticResource allCustomersListBox}">
    </ListBox>
</DockPanel>

GetAll()是我的ViewModel中的ObservableCollection属性:

public ObservableCollection<Customer> GetAll
{
    get
    {
        return Customer.GetAll();
    }
}

进而调用 GetAll() 模型方法,该方法读取 XML 文件以填充 ObservableCollection。

public static ObservableCollection<Customer> GetAll()
{
    ObservableCollection<Customer> customers = new ObservableCollection<Customer>();

    XDocument xmlDoc = XDocument.Load(Customer.GetXmlFilePathAndFileName());
    var customerObjects = from customer in xmlDoc.Descendants("customer")
                          select new Customer
                          {
                              Id = (int)customer.Element("id"),
                              FirstName = customer.Element("firstName").Value,
                              LastName = customer.Element("lastName").Value,
                              Age = (int)customer.Element("age")
                          };
    foreach (var customerObject in customerObjects)
    {
        Customer customer = new Customer();

        customer.Id = customerObject.Id;
        customer.FirstName = customerObject.FirstName;
        customer.LastName = customerObject.LastName;
        customer.Age = customerObject.Age;

        customers.Add(customer);
    }

    return customers;
}

除了当用户进入另一个视图之后,编辑XML文件并返回到这个视图时仍显示旧数据,所有的一切都运作正常。

我怎样才能告诉该视图“刷新其绑定”,以便它显示实际数据。

感觉我在这里使用了太多HTML/HTTP隐喻来处理WPF,我感到有一种更自然的方法可以让ObservableCollection自我更新,因此得名,但目前这是我能够让用户编辑WPF应用程序中的数据的唯一方法。因此,在这里任何层面上的帮助都受到赞赏。

3个回答

16

ItemsControl请求其绑定一次并缓存引用。

如果集合对象的内容被修改,并且实现了INotifyCollectionChanged(如ObservableCollection),它将捕获任何添加或删除的对象。

现在,如果您希望绑定向ListBox提供一个新的集合对象,则可以让您的视图模型实现INotifyPropertyChanged并引发PropertyChanged事件,其中传递GetAll作为属性名称。 这将有警告绑定该属性值已更改(有一个新的ObservableCollection待捕获),它将提供给ListBox,后者将重新生成其项。

只要您从应用程序中实现更改,处理GetAll返回的ObservableCollection,您就可以添加和删除,列表将保持同步。当您想要捕获外部修改(可能会有一个刷新按钮,或者自然的重载整个文件的点)时,您可以让您的视图模型引发PropertyChanged事件,这将自动调用属性getter,后者将调用静态方法,后者将返回一个全新的集合。

挑剔者注意:为什么要给属性命名方法?


我将GetAll()更改为GetAll,谢谢。问题是我有两个视图,它们各自从它们的ViewModels获取一个单独的GetAll ObservableCollection,当一个ObservableCollection更改时,另一个不会更改。我需要在全局某处存储它们吗? - Edward Tanguay
如果在编辑期间两个视图都应该同步,那么是的,你需要以某种方式共享同一个对象。 在您的情况下,可能会有一个数据访问系统来加载和缓存集合,每个ViewModel将请求当前集合。这样它们两个都知道彼此的修改。 现在,如果您需要从文件重新加载集合,您将有一种方法来警告每个ViewModel,集合对象已更改,以便它们在获取新引用后可以引发其PropertyChanged事件。 - Denis Troller
所以目前我的解决方案是每次加载用户控件(视图)时刷新数据源,效果很好,谢谢! - Edward Tanguay
知道这个缓存的位置就好了。 (我有一个问题,缓存在不应该更新时正在更新。)觉得加上这个信息怎么样? - Vaccano
确保将双向绑定添加到列表中。 - Aravind Mungara

11

以下代码与将对象添加到集合中的方式相同:

CollectionViewSource.GetDefaultView(CustomObservableCollection).Refresh();

0

在加载ObservableCollection和XML文件时,请保留一个引用及其最后修改时间戳。每当窗口获得焦点时,请检查磁盘文件的时间戳。如果已更改,则清除并重新填充ObservableCollection。GUI自动侦听来自ObservableCollection的更改事件,并在修改集合内容时自动重新填充。


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