Pergunta

I am relatively new to WPF and the MVVM model, but after hours of searching and reading articles regarding the matter, I have not come up with a definitive solution to this.

1) Model: I have an EF model relying on an SQL Express database. For this example, I will use a property named Visits, a DbSet(Of Visit).

2) ViewModel: an ObservableCollection(Of Visit). It is declared as such:

Private _Visits As ObservableCollection(Of Visit)
Public Property Visits As ObservableCollection(Of Visit)
    Get
        Return _Visits
    End Get
    Set(value As ObservableCollection(Of Visit))
        _Visits = value
        RaisePropertyChanged("Visits")
    End Set
End Property
...
Visits = New ObservableCollection(Of Visit)(
    From V In Application.context.Visits
    Where V.IsRobotGenerated AndAlso
    Not V.IsSynced
)

3) View: a WPF datagrid.

<DataGrid
    x:Name="grdVisits"
    ItemsSource="{
        Binding Path=Visits,
        RelativeSource={RelativeSource FindAncestor, AncestorType=Window}
    }"
/>

Now I have a background thread which modifies the EF data directly (does all CRUD operations). What I want is the datagrid to reflect these changes as they happen.

What I am doing right now is replace the Visits ObservableCollection by re-calling the constructor above, which results to 2 drawbacks:

1) Performance wise I suppose it is not the best choice, especially when we are talking about quite a few thousands of rows (each with its RowDetails).

2) The user has in the meantime scrolled down the datagrid or opened a RowDetailsTemplate. His position and everything is lost if the entire collection is reset.

I have read somewhere about DependencyProperties but I do not have time to go through it thoroughly since I have no clue if it is a pointer to the right direction. If it is, I will be happy to do so.

Any help will be greatly appreciated.

Foi útil?

Solução

When you add or remove elements from an ObservableCollection bound to an ItemsSource, those changes are instantly reflected so what you need to do is simply to modify the ObservableCollection accordingly as your CRUD operations take place.

Bear in mind that if you are using a version of .NET prior to 4.5 you'll need to dispatch the ObservableCollection changes to the UI thread.

UPDATE: answering to the comment

What about the following scenario: two datagrids in the view, which are bound to two different ObservableCollections. However, these ObservableCollections are created with a different constructor so as to apply filtering to the underlying Visits. Can you provide a bare bones example as to how I can accomplish the aforementioned?

Filtering is a different story. It is supported by an intermediate layer set between your collection and the items control (ObservableCollection and DataGrid respectively in this case): collection views. Actually, you always bind to collection views, not to the collections directly.

So, for your scenario you'd bind both DataGrids to the same underlying collection but using two different collection views, one for each DataGrid. This way, the data stays the same and synchronized with whatever you need it to be (your CRUD operations for instance). However, each DataGrid can display a subset of the data based on filtering, sorted and/or grouped in a different way.

I'd suggest you take a look into the MSDN article regarding data binding to collections.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top