WPF DataGrid updating items with .Refresh
I am using a datagridview to show my own items in it as List(Of MyStuff)
and it works quiete well. When my class is changing the content the DataGrid does not change. I need to do DataGrid1.Items.Refresh
and the items becomes updates.
But now my list contains 700 items and the .Refresh
methode takes about 15 seconds just because one item changed. I've searched for any "UpdateContent" or "RowUpdate" or "RefreshRow" but found nothing. How is the right way to update single Rows?
Private LCommand As New List(Of MyLogEntry)
Me.dgv.DataContext = Me.LCommand
Me._LastUpdate = DateTime.MinValue
Me._CurrentIndex = -1
Call UpdateDgv()
Private Sub UpdateDgv()
Application.Current.Dispatcher.Invoke(AsyncRefresh)
End Sub
Private Sub RefreshDgvAsync()
Try
Me.dgv.SelectedIndex = Me._CurrentIndex
Me.dgv.ScrollIntoView(Me.dgv.SelectedItem)
Catch ex As Exception
End Try
If DateTime.Now.Subtract(Me._LastUpdate).TotalSeconds > 60 Then Me.dgv.Items.Refresh()
Me._LastUpdate = DateTime.Now
End Sub
<DataGrid x:Name="dgv" Grid.Row="1" RowHeight="20" AutoGenerateColumns="False" Grid.Column="1" ItemsSource="{Binding}" CanUserAddRows="False" VerticalScrollBarVisibility="Auto" ClipToBounds="True" GridLinesVisibility="Horizontal">
<DataGrid.Columns>
<DataGridTextColumn Header开发者_开发问答="N°" Binding="{Binding Index}" Width="SizeToCells" MinWidth="30" IsReadOnly="True" />
<!--<DataGridCheckBoxColumn Header="OK" Binding="{Binding Successfully}" Width="SizeToCells" MinWidth="35" IsReadOnly="True" Visibility="Collapsed" />-->
<DataGridTemplateColumn Header="State" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image x:Name="imgState" Source="{Binding StateImageUrl}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Logentry" Binding="{Binding Title}" Width="SizeToHeader" MinWidth="80" IsReadOnly="True" FontWeight="Bold" />
<DataGridTextColumn Header="Action" Binding="{Binding Description}" Width="SizeToCells" MinWidth="80" IsReadOnly="True" FontSize="12" />
<DataGridCheckBoxColumn Header="Available" Binding="{Binding Necessary}" Width="Auto" MinWidth="35" IsReadOnly="True" />
<DataGridTextColumn Header="Log" Binding="{Binding Log}" Width="*" MinWidth="50" IsReadOnly="False" FontSize="8" Foreground="Gray" />
</DataGrid.Columns>
</DataGrid>
It is not very clear for me why do you need to refresh your items at all. If you need to observe log entries collection changes then use ObservableCollection<LogEntry>
, if you need to update cells when something in LogEntry changes then make it observable by implementing INotifyPropertyChanged
.
When you call Refresh on underlying CollectionView all item containers are regenerated. And it takes a lot of time espacially when virtuallization is disabled.
Implement INotifyPropertyChanged at your collection.
Instead of having a List use ObserverableCollection<type>.
At any setter of MyLogEntry properties invoke the PropertyChangedEventHandler.
C# code (no testing):
public class MyLogEntry : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private object _myProperty;
public object MyProperty{
get { return _myProperty; }
set {
_myProperty = value;
OnPropertyChanged("MyProperty");
}
}
protected void OnPropertyChanged(string name){
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null){
handler(this, new PropertyChangedEventArgs(name));
}
}
}
精彩评论