Seeker Help

Seeker Help

  • NA
  • 8
  • 4.4k

WPF, MVVM, DataGrid not dynamically updating

May 17 2017 10:24 AM

Hi,

I have a View called View1 that contains a list with CheckBoxes, when the user checks the CheckBox of some items they get copied to a View called View2 into a DataGrid that has 3 Columns, 1st Column is the ItemName, 2nd Columns is ItemGrade which is a ComboBox with selections 0, 1, 2, 3 and 3rd Column is ItemScore which is calculated with an equation based on how many rows in the DataGrid and what the user selected in the ComboBox, the equation is inside an if statement as follows:

public void OnItemGradeChanged()

{
if (SelectedViewModelObj.Items.Count != 0)
ItemMaxScore = 100m / Convert.ToDecimal(SelectedViewModelObj.Items.Count);
if (Convert.ToDecimal(ItemGrade) == 0m)
{
ItemScore = (decimal)(ItemMaxScore) * 0m;
}
else if (Convert.ToDecimal(ItemGrade) == 1m)
{
ItemScore = (decimal)(ItemMaxScore) * 6m / 10m;
}
else if (Convert.ToDecimal(ItemGrade) == 2m)
{
ItemScore = (decimal)(ItemMaxScore) * 8m / 10m;
}
else if (Convert.ToDecimal(ItemGrade) == 3m)
{
ItemScore = (decimal)(ItemMaxScore) * 1m;
}
}

Please note the ItemMaxScore used in the above code is calculated based on how many items are there in the DataGrid. I used this equation to calculate the ItemMaxScore so that the total score of all the items is always 100% no matter how many items the user add to the DataGrid.

ItemMaxScore = 100m / Convert.ToDecimal(SelectedViewModelObj.Items.Count);


Here is the DataGrid in View2.xaml

<Grid ShowGridLines="false">
<Grid ShowGridLines="false" Grid.Row="0">
</Grid>
<ScrollViewer Grid.Row="1" PreviewMouseWheel="UIElement_OnPreviewMouseWheel">
<DataGrid x:Name="Grd" AutoGenerateColumns="False" ItemsSource="{Binding Items, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Columns>
<DataGridCheckBoxColumn x:Name="ChkClm" Width="30" Binding="{Binding ItemIsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn x:Name="TaskClm" Width="*" Header=" Task" Binding="{Binding ItemName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTemplateColumn x:Name="GradeClm" Header=" Grade" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="CBClm"
ItemsSource="{Binding ItemGrades, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding ItemGrade, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="ScoreClm" Width="100" Header=" Score" Binding="{Binding ItemScore, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</Grid>

Here is my model, that has the calculation


[ImplementPropertyChanged]
public class Property
{
public bool ItemIsChecked { get; set; }
public string ItemName { get; set; }
public SelectedViewModel SelectedViewModelObj { get; set; }
public List<decimal> ItemGrades { get; set; }
public decimal ItemGrade { get; set; }
public decimal ItemMaxScore { get; set; }
public decimal ItemScore { get; set; }
public Property(string itemName, List<decimal> itemGrades, decimal itemGrade, SelectedViewModel selectedViewModel)
{
itemName = ItemName;
selectedViewModelObj = SelectedViewModel;
itemGrades = ItemGrades;
itemGrade = ItemGrade;
}
public void OnItemIsCheckedChanged()
{
if (ItemIsChecked)
{
SelectedViewModelObj.Items.Add(this);
}
else
{
SelectedViewModelObj.Items.Remove(this);
}
}
public void OnItemGradeChanged()
{
if (SelectedViewModelObj.Items.Count != 0)
ItemMaxScore = 100m / Convert.ToDecimal(SelectedViewModelObj.Items.Count);
if (Convert.ToDecimal(ItemGrade) == 0m)
{
ItemScore = (decimal)(ItemMaxScore) * 0m;
}
else if (Convert.ToDecimal(ItemGrade) == 1m)
{
ItemScore = (decimal)(ItemMaxScore) * 6m / 10m;
}
else if (Convert.ToDecimal(ItemGrade) == 2m)
{
ItemScore = (decimal)(ItemMaxScore) * 8m / 10m;
}
else if (Convert.ToDecimal(ItemGrade) == 3m)
{
ItemScore = (decimal)(ItemMaxScore) * 1m;
}
}
}

The calculation is done correctly when the user select items from View1, they get copied to the DataGrid in View2 then the user select value from the ComboBox in the DataGrid in View2, then the Score gets calculated.

The problem happens if the user went back to View1 and selected more items, then the equation that calculates the ItemMaxScore gets executed but the Score Column that appeared in the DataGrid does not update the ItemScore of the old items but the ItemScore of the new items will be according to the new correct values of the equation.

Question is: how to get the DataGrid to update the ItemScore of all items whenever the ItemMaxScore is changed?

I have implemented [ImplementPropertyChanged] using fody, isn't that should update the DataGrid when the property changed?


full demo code is here that recreates the problem, the Demo.zip file has the complete demo solution

https://github.com/NewCoderNotInTown/demo-for-fody-issue

Attachment: Demo.zip

Answers (1)