Reputation: 371
I have a problem where a Silverlight UI datagrid is not updating, when the underlying data property changes. I can make it work if I introduce a temp variable and update the data in one chunk, but do not understand why the original code does not work.
This is the xaml code of the web UI part:
<C1:C1DataGrid ItemsSource="{Binding DeliveryAccuracyTotals}"
HeadersVisibility="Column"
AutoGenerateColumns="False">
<C1:C1DataGrid.Columns>
<C1:DataGridDateTimeColumn Binding="{Binding PlannedAcceptanceDate}"
Header="{Binding Date,
Source={StaticResource res}}"
Format="dd.MM.yyyy" />
<C1:DataGridNumericColumn Binding="{Binding OKcount}"
Header="{Binding OK, Source={StaticResource res}}" />
<C1:DataGridNumericColumn Binding="{Binding NOKcount}"
Header="{Binding NOK, Source={StaticResource res}}" />
<C1:DataGridNumericColumn Binding="{Binding OKpercentage}"
Header="%" Format="0.##"/>
</C1:C1DataGrid.Columns>
</C1:C1DataGrid>
I have a callback handler for handling the data when the async data fetch finishes:
private void handleDeliveryAccuracyReportDataCallBack(List<DeliveryAccuracyReportDataRow> data)
{
DeliveryAccuracyTotals.Clear();
if (data != null)
{
data.GroupBy(row => row.PlannedAcceptanceDate)
.ToList()
.ForEach(group =>
DeliveryAccuracyTotals.Add(new DeliveryAccuracyTotalData(group.ToList())));
}
}
This uses the following property to inform the UI of changes.
public List<DeliveryAccuracyTotalData> DeliveryAccuracyTotals
{
get
{
if (_deliveryAccuracytotals == null)
{
_deliveryAccuracytotals = new List<DeliveryAccuracyTotalData>();
}
return _deliveryAccuracytotals;
}
private set
{
_deliveryAccuracytotals = value;
NotifyPropertyChanged("DeliveryAccuracyTotals");
}
}
If I run this, the DeliveryAccuracyTotals property gets populated properly with the new data but the UI does not show the new data!
However, when I change the callback code to this, it works:
private void handleDeliveryAccuracyReportDataCallBack(List<DeliveryAccuracyReportDataRow> data)
{
var temp = new List<DeliveryAccuracyTotalData>();
if (data != null)
{
data.GroupBy(row => row.PlannedAcceptanceDate)
.ToList()
.ForEach(group =>
temp.Add(new DeliveryAccuracyTotalData(group.ToList())));
}
DeliveryAccuracyTotals = temp;
}
Can anyone explain what is going on in here? I suspect it has something to do with the ForEach() and/or closures.
Upvotes: 1
Views: 72
Reputation: 15772
Although Servy is correct is his analysis I would say his advice is not the best. Observable collection would not fix your problem for you. Also rebinding a new collection each time will reset the state of your tree view (bad UX).
You should look into the various PropertyChanged aware Linq query implementations. Such as, but not limited to
I would suggest RxUI
Upvotes: 1
Reputation: 203834
You only fire NotifyPropertyChanged
when you set a new value to the DeliveryAccuracyTotals
field. You don't fire the event when the list is mutated, only when an entirely new list is set.
Were the property to be an ObservableCollection
then the UI would be able to add a handler to pick up notifications of mutating to the collection itself, and not just changes to the variable holding the list, but if you're going to completely re-create the collection from scratch anyway, rather than just make a few changes, it's not really a problem to just assign a new collection to that property.
Upvotes: 2