【问题标题】:How to get an ItemsSource to refresh its bind?如何让 ItemsSource 刷新其绑定?
【发布时间】:2010-10-22 20:17:29
【问题描述】:

我有一个显示绑定到 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 应用程序中编辑数据。因此,这里感谢任何级别的帮助。

【问题讨论】:

    标签: wpf mvvm binding


    【解决方案1】:

    ItemsControl 请求其绑定一次,然后缓存引用。

    如果集合对象的内容被修改,并且它实现了INotifyCollectionChanged(就像ObservableCollection 所做的那样),它将拾取任何添加或删除的对象。

    现在,如果您希望绑定为ListBox 提供新的集合对象,您可以让您的视图模型实现INotifyPropertyChanged 并引发PropertyChanged,传入GetAll 作为属性名称。 这将产生警告属性值已更改的绑定的效果(有一个新的ObservableCollection 准备好被拾取),它将提供给ListBox,后者将重新生成其项目。

    因此,只要您对应用程序进行更改,处理GetAll 返回的ObservableCollection,您就可以添加和删除,并且列表将保持同步。当您想要获取外部修改时(您可能在某处有一个刷新按钮,或者重新加载整个文件有意义的自然点),您可以让您的视图模型引发 PropertyChanged 事件,该事件将自动调用属性 getter,它将调用静态方法,该方法将返回一个新的集合。

    Nitpicker 注意:为什么要为属性指定方法名称?

    【讨论】:

    • 我将 GetAll() 更改为 GetAll,谢谢。问题是我有两个视图,每个视图都从各自的 ViewModel 中获得一个单独的 GetAll ObservableCollection,当一个 ObservableCollection 发生变化时,另一个不会改变。我需要将这些全局存储在某个地方吗?
    • 如果两个视图都应该在编辑期间同步,那么是的,您需要以某种方式共享同一个对象。在您的情况下,可能有一个数据访问系统来加载和缓存集合,然后每个 ViewModel 都会请求当前集合。这样他们都知道彼此的修改。现在,如果您需要从文件中重新加载集合,您将有办法警告每个视图模型集合对象已更改,以便他们在获得新引用后可以引发 PropertyChanged 事件。
    • 所以现在我的解决方案是在每次加载用户控件(视图)时刷新 DataSource,效果很好,谢谢!
    • 当然很高兴知道缓存在哪里。 (我有一个问题,缓存在不应该更新的时候更新。)想用那一点信息更新吗?
    • 确保将双向绑定添加到列表
    【解决方案2】:

    下面的工作与我们删除以在集合中添加对象时相同:

    CollectionViewSource.GetDefaultView(CustomObservableCollection).Refresh();
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多