Tuesday, January 6, 2009

WPF Datagrid Items Refresh

So, I have this WPF datagrid, and it's quite happy in the way it works. With a single exception. Some background, I'm not doing the base behavior for editing/adding, but rather have a separate control outside the grid which is responsible for that behavior (as it is also the control responsible for adding the initial element).

But I was having a problem, and it was with the Grid's UI.

My changes and additions were not making their way into the UI display. No matter how many times I invalidated the User Interface it just would not get displayed. And this was not just for Updates, but also for Inserts and Deletes.

VERY much annoying.

But, I wouldn't be here if I didn't have a solution.

As stated, my initial try was to use the Datagrid.InvalidateUI command, as that's basically what I was trying to do: repaint the grid. What I wasn't doing with that was telling the Datagrid to look at the underlying datasource and refresh the UI from that.

The magic command? Datagrid.Items.Refresh()

Yeah, I did feel a bit silly after finding that out. Of course I blame it on the fact that I've spent too much time in the ASP.NET arena where I can force a data-rebinding by calling the DataBind method of the object. Oh well, I solved the problem, so I'm all sorts of happy.

28 comments:

Anonymous said...

Hello there,

try this one :
CollectionViewSource.GetDefaultView(yourGrid.ItemsSource).Refresh();

Stephen Wrighton said...

Yes, that seems to work as well, but is it better (more efficient, etc) than using the simpler: myGrid.Items.Refresh

Anonymous said...

My WPF data grid doesn't seem to have an Items property on which to call Refresh(). Nor is there a CollectionViewSource in scope.

??

Stephen Wrighton said...

I use the WPF Toolkit's DataGrid control, and it has a .Items collection which has a .Refresh method.

Gaurav said...

whether refresh() method repaints whole of the data in grid or it just updates the changes done to dataGrid ?

Stephen Wrighton said...

From my understanding (and I could be wrong here) the refresh is refreshing the datagrid's ITEMS collection.

To invalidate/redraw the datagrid itself there is the InvalidateVisual method of the control.

Mykhaylo Khodorev said...

I tried to do same - no luck.
My DataGrid is binded to the IEnumerable like this:

AccDataGrid.ItemsSource =
from account in _myDataSet.Accounts
select new Account(account);

When I add new item to the _myDataSet.Accounts I can immediately see it in the AccDataGrid.ItemsSource. But I don't see any changes in AccDataGrid.Items. Even after AccDataGrid.Items.Refresh() nothing changes.

Did I miss something?

Stephen Wrighton said...

Mykhaylo Khodorev short answer: the datagrid is not bound to the Accounts DataTable in your dataset.

Long answer, look here: http://programmer.wrighton.org/2009/07/wpf-datagrid-items-refresh-part-ii.html

ksvimal said...

I have binded my DataGrid with List as below.
XAML: (Tag removed)
my:DataGrid x:Name="DataGrid1" ItemSource="{Binding}" AutoGenerateColumns="True"

C#:
DataGrid1.DataContext = AccountList



If dont sort any of the the WPF DataGrid column, then DataGrid1.Items.Refresh() works fine.

If i do any sorting and delete/add the any item in the AccountList
then only it is not reflecting.

Actually while debugging i can see reflection of delete/add in the DataGrid1. But it is just not visibile in the UI (I cant see the chahges happened in DataGrid).

Please help me what could be the problem?

Stephen Wrighton said...

@ksvimal - There's not really a lot of information in the sample that you've given for me to say. I don't know even know what type of collection that "accountList" is.

That said, it's possible that the problem is that the "accountList" object is not getting updated -- or even the in-memory version that is stored in the datagrid's ITEM property is not getting updated when you update the list in the collection.

Also remember that a standard generic LIST does not have SORTING capability. But this may help you with that: http://elegantcode.com/2009/05/14/write-a-sortable-observablecollection-for-wpf/

Anonymous said...

Thanx man, that is really magic command:)

Stephen Wrighton said...

anonymous- a pleasure. thanks for the comment!

Home Page said...

You are my saviour! Thanks for your post!

Anonymous said...

Thanks. You helped me.

Lubo Antonov said...

Thanks, this saved a lot of frustration! Every day it seems like my finely honed Windows programming skills are only an obstacle when working with WPF :)

Anonymous said...

If you are working with Entity Framework MyDataGrid.Items.Refresh() doesn't seem to work - at least not with deep heirarchal collections of collections. (At least not for me).

Instead, you have to re-assign your CollectionViewSource.Source after making changes. This automatically updates a DataGrid with the most recent changes.

It's the easiest most straightforward technique I know of to dynamically update DataGrid.

Stephen Wrighton said...

@Anonymous - That makes sense, but I've not utilized the Entity Framework that much. I prefer LINQ and/or working with my own data layer rolled out via OBSERVABLE collections for this.

Anonymous said...

AccDataGrid.ItemsSource =
from account in _myDataSet.Accounts
select new Account(account);

For this format of data binding, the refresh code would be:

_myDataSet.Refresh(System.Data.Objects.RefreshMode.StoreWins, AccDataGrid.ItemsSource);

This call alone refreshes the bound data grid.

Ahhhh! said...

Thanks for the answer. Working in WPF is a pain. I guess it takes 5 hours to figure one thing out, then 5 minutes for the second time. WPF is over-rated. I think I am bitter! Guess I'll get over it.

leomoty said...

I have quite a large number of Data that I want to display but when I keep updating it for like each 1 second it takes too much processing power. Is there any better way to refresh only partial data or something?

Stephen Wrighton said...

@leomoty - There's a number of moving parts that you're going to have going on here.

The first is that you need to look into virtualizing the stack panel in your data template for the grid. This is to keep it so that the only things consuming UI resources are those elements currently drawn on the screen.

Next, I have to ask is a data refresh every second needed? If not, then only poll it every 30 seconds -- or better yet, have the repository for your data, tell you when it's changed. In SQL Client, the SQL Depenedency classes to only reload the values when the SQL SERVER data set has changed.

leomoty said...

Actually I'm not getting the data from a SQL, I'm using a dictionary where the object part corresponding my is the data.
Yea, actually it's not really needed to update every second if... nothing is changed. To solve that I implemented INotifyPropertyChanged and the CPU usage went down from 50% to 20%. Although i'd like to achieve even less CPU power just to update the data.

Anonymous said...

Hello Stephen,
As i am using WPF Toolkit, and not datagrid, that refresh method doesn't work for me.

Anonymous said...

Thanks for the post! Been struggling all day with my DataGrid, wondering what's wrong. Was it the DataContext? Or the ItemsSource? Was it the fact I was using DatagGrid instead of DataGridView? Was there conflicting information in the XAML to the .cs ? Should I be using Binding or BindingList? Was it that "AutoGenerate..." was ticked in the properties but not mentioned in the corresponding XAML?
Well , it was none of these and all it needed was an Items Refresh as you mentioned so many thanks for stopping me giving up in despair !!!!

Eduardo Portes Thiago said...

Man... Thank you very very much!! That's really a magical command, that saved me from killing myself!

After days over days searching for a solution, I found it here.

Tkz again wizard Stephen!

Binho e Dani said...

Worked well for me! Thanks!

Ivan Flores said...

I really love you, you stop 2 hours of searching man :D thanks

Arielito Gibbs said...

You saved my life, after 3 days trying to update a datagrid from a combobox.
THANK YOU!!!

Blog Widget by LinkWithin