none
wpf, MVVM, datagrid column update according to calculation in the code. RRS feed

  • Question

  • Hi and sorry for the long question,

    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.RowDefinitions>
                    <RowDefinition Height="30"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <Grid ShowGridLines="false" Grid.Row="0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="30"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="100"/>
                    </Grid.ColumnDefinitions>
                    <Label Grid.Column="0" Width="30" Content="" Style="{StaticResource DataGridColumnHeaderLabel}"/>
                    <Label Grid.Column="1" Width="Auto" Content=" Task" Style="{StaticResource DataGridColumnHeaderLabel}"/>
                    <Label Grid.Column="2" Width="100" Content=" Grade" Style="{StaticResource DataGridColumnHeaderLabel}"/>
                </Grid>
                <ScrollViewer Grid.Row="1" Style="{StaticResource ScrollViewerStyle}">
                    <DataGrid x:Name="Grd" ItemsSource="{Binding Items, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource DataGridStyle}">
                    <DataGrid.Columns>
                            <DataGridTextColumn x:Name="TaskClm" Width="*" Binding="{Binding ItemName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
                            <DataGridTemplateColumn x:Name="GradeClm" Width="100">
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <ComboBox x:Name="CBClm" Margin="0,0,-1,0" Style="{StaticResource ComboBoxStyle}" 
                                          ItemsSource="{Binding ItemGrades}" SelectedItem="{Binding ItemGrade, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>
                    </DataGrid.Columns>
                </DataGrid>
            </ScrollViewer>
        </Grid>
        </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?

    • Moved by Bob Ding Friday, May 19, 2017 5:50 PM
    Sunday, May 14, 2017 6:17 PM

All replies

  • Hi,

    >> 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.

    According to your description,  I suggest you try to implements INotifyPropertyChanged interface for "ItemScore " to support one-way and two-way bindings.

    How to: Implement Property Change Notification

    https://msdn.microsoft.com/en-us/library/ms743695%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

    If I have any misunderstanding, I suggest you can upload your demo to OneDrive(Including your test material). We can download it and debugging. This will help us quickly analyze your problem.
    Share OneDrive files and folders:
    https://support.office.com/en-us/article/Share-OneDrive-files-and-folders-9fcc2f7d-de0c-4cec-93b0-a82024800c07

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by Bob Ding Monday, May 15, 2017 5:24 AM
    Monday, May 15, 2017 5:24 AM
  • Hi,

    thanks for your reply. I have implemented [ImplementPropertyChanged] using fody isn't that the same?

    Monday, May 15, 2017 7:50 AM
  • Hello,

    >> I have implemented [ImplementPropertyChanged] using fody isn't that the same?

    Since fody is the third party source which is outside of this forum scope of support ,I suggest you ask you question here: https://github.com/Fody/PropertyChanged/issues

    Thank you for your understanding and cooperation.

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, May 16, 2017 5:31 AM
  • ok, sorry for that and thanks again for your help.
    Tuesday, May 16, 2017 6:29 AM