Search code examples
c#wpfwpfdatagrid

DataGridTextColumn displays NaN when button is clicked


I have a DataGrid that displays a list of different oil names, percentage of their usage, drop count and add/subtract drop buttons per row.

For the sake of simplicity, lets say the names are Pennziol, Castrol and Valvoline. Their initial percentage usage value (suppose to be float) and drop count (int) are 0. if the "+" button for a row is clicked, the drop count will increment. If Pennziol is then incremented by 1, its percentage usage will become 100% with the other remaining 0%. If Castrol is then clicked twice, its percentage will be 66.6% and Pennziol will be reduced to 33.3% with Valvoline remaining 0%.

My code is suppose to be doing this updating the data every time a button is clicked, but it returns the value in all Formula % column cells as NaN.

MainWindow.xaml.cs

private OilList mOilList = new OilList();

    public MainWindow()
    {
        InitializeComponent();

        // Add Oils to Oil Grid Table
        foreach (Oil oil in mOilList.Oils)
        {
            OilGridXaml.Items.Add(oil);        
        }          
    }


    private void Button_Click_Increment(object sender, RoutedEventArgs e)
    {        
        Oil oil = ((FrameworkElement)sender).DataContext as Oil;
        oil.AddDrop();

        mOilList.UpdateFormulaWeight();

        PerfumeGridXaml.Items.Refresh();
    }

Oil.cs

public void AddDrop()
    {
        mDropCount++;
        mOilAmount = mDropSize * mDropCount;
        NotifyPropertyChanged("DropCount");
    }

public float UsagePercentage
    {
        get { return mUsagePercentage; }
        set
        {
            if (mUsagePercentage != value)
            { 
                mUsagePercentage = value;
                NotifyPropertyChanged("UsagePercentage");
            }
        }
    }

OilList.cs

public void UpdateFormulaWeight()
    {
        foreach (Oil oil in mOils)
            mFormulaTotalWeight += oil.TotalWeight;

        foreach (Oil oil in mOils)
        {
            oil.UsagePercentage = (oil.TotalWeight / mFormulaTotalWeight) * 100f;
            NotifyPropertyChanged("UsagePercentage");
        }
    }

MainWindow.xaml

<DataGrid x:name="OilGridXaml" ... ItemsSource="{Binding}">...
<!-- USAGE PERCENTAGE -->
<DataGridTextColumn Header="Formula %" Foreground="LightGray" Binding="{Binding UsagePercentage, StringFormat={}{0:F2}%}" IsReadOnly="True" Width="64">
    <DataGridTextColumn.CellStyle>
        <Style TargetType="DataGridCell">
            <Setter Property="Background" Value="#1e1e1e"/>
        </Style>
    </DataGridTextColumn.CellStyle>

    <DataGridTextColumn.ElementStyle>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="TextBlock.VerticalAlignment" Value="Center" />
            <Setter Property="TextBlock.TextAlignment" Value="Center" />
        </Style>
    </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

<!-- DROP COUNT -->
<DataGridTextColumn x:Name="Cell_Drop_Count" Header="Drop Count" Foreground="LightGray" Binding="{Binding DropCount}" Width="*">
    <DataGridTextColumn.CellStyle>
        <Style TargetType="DataGridCell">
            <Setter Property="Background" Value="#1e1e1e"/>
        </Style>
    </DataGridTextColumn.CellStyle>

    <DataGridTextColumn.ElementStyle>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="TextBlock.VerticalAlignment" Value="Center" />
            <Setter Property="TextBlock.TextAlignment" Value="Center" />
        </Style>
    </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

UPDATE

Oil and OilList inherits INotifyPropertyChanged with same effect

public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }

Solution

  • I see no PropertyChanged event fired in your UsagePercentage. I think the value of your property will change properly, but the DataGrid won't update then. So it stays to its initial value which seemed to be NaN.

    The PerfumeGridXaml.Items.Refresh() will only recreate the view, but not refresh the ItemsSource nor any of its elements.