2009-04-30 16 views
8

Tengo una vista que muestra un cuadro de lista que está obligado a GetAll():¿Cómo obtener un ItemsSource para actualizar su enlace?

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

GetAll() es una propiedad ObservableCollection en mi modelo de vista:

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

cuales a su vez llama a un método GetAll() modelo que lee un archivo XML para rellenar el 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; 
} 

Todo esto funciona bien, excepto cuando el usuario pasa a otra vista , edita el archivo XML y vuelve a este punto de vista, donde los datos antiguos se sigue mostrando.

Cómo puedo decirle a esta vista que "actualice sus enlaces" para que muestre los datos reales.

Parece que estoy pasando por WPF aquí con demasiada metáfora HTML/HTTP, tengo la sensación de que hay una manera más natural de hacer que se actualice el ObservableCollection, de ahí su nombre, pero esta es la única forma en que puede hacer que el usuario pueda editar datos en una aplicación WPF en este momento. Así que la ayuda en cualquier nivel es apreciada aquí.

Respuesta

12

Un ItemsControl solicita su unión una vez y guarda en caché la referencia a partir de entonces.

Si se modifica el contenido del objeto de recopilación e implementa INotifyCollectionChanged (como ObservableCollection), recogerá cualquier objeto agregado o eliminado.

Ahora, si desea que la unión para suministrar un nuevo objeto a la colección ListBox, usted puede tener su punto de vista-modelo de implementar INotifyPropertyChanged y elevar PropertyChanged, pasando GetAll como el nombre de la propiedad. Esto tendrá el efecto de advertir el enlace que ha cambiado el valor de la propiedad (hay un nuevo ObservableCollection listo para ser recogido), que suministrará al ListBox, que volverá a generar sus artículos.

Por lo tanto, siempre que realice cambios desde su aplicación, trabajando en ObservableCollection devuelto por GetAll, puede agregar y eliminar y la lista se mantendrá sincronizada. Cuando desee recoger modificaciones externas (es posible que tenga un botón de actualización en alguna parte, o un punto natural donde tenga sentido volver a cargar todo el archivo), puede hacer que su modelo visualice el evento PropertyChanged, que llamará automáticamente a la propiedad getter, que llamará al método estático, que devolverá una nueva colección nueva.

Nota de Nitpicker: ¿por qué le das nombres de métodos a las propiedades?

+0

me cambió GetAll() para GetAll, gracias. El problema es que tengo dos vistas que obtienen GetAll ObservableCollection por separado de sus respectivos ViewModels y cuando una ObservableCollection cambia, la otra no cambia. ¿Debo almacenar estos globalmente en alguna parte? –

+0

Si se supone que ambas vistas se sincronizarán durante la edición, entonces sí, debe compartir el mismo objeto de alguna manera. En su caso, podría haber un sistema de acceso a datos que carga y almacena en caché la colección, y cada ViewModel solicitaría la colección actual. De esa forma, ambos son conscientes de las modificaciones de los demás. Ahora, si necesita volver a cargar la colección desde el archivo, tendría una forma de advertir a cada modelo de vista que el objeto de colección ha cambiado, para que puedan generar su evento PropertyChanged una vez que hayan obtenido la nueva referencia. –

+0

Así que por ahora mi solución en cuanto a actualizar el DataSource cada vez que se carga el control (vista) del usuario, funciona muy bien, ¡gracias! –

0

Mantenga una referencia a su ObservableCollection y la última hora de modificación del archivo XML desde el momento en que lo cargó. Siempre que la ventana se enfoque, verifique la marca de tiempo en el archivo del disco. Si ha cambiado, borre y vuelva a llenar el ObservableCollection. La GUI escuchará automáticamente los eventos de cambio desde ObservableCollection y se volverá a llenar automáticamente cuando modifique los contenidos de la colección.

7

A continuación la línea de trabajo mismo que cuando eliminamos añadir objetos en una colección:

CollectionViewSource.GetDefaultView(CustomObservableCollection).Refresh(); 
Cuestiones relacionadas