0
votes

My problem is that I'm trying to display a ProgressBar value inside of a DataGridTemplateColumn, and the binding isn't wanting to work. It will work for my TextBlock (which is in the same Grid), but not the ProgressBar.

I've gone to many references (Microsoft and StackOverFlow) to try and find my solution. However, none of them really help solve my solution with this binding. Main Helpful Examples: Progress Bar Bind Value , https://www.wpf-tutorial.com/misc-controls/the-progressbar-control/ , WPF how to display text on progress bar

Also, I was originally passing PercentFull a double value (which I don't think worked) so that is why I'm passing it an Int value instead. However, either way the binding doesn't want to cooperate.

XAML

<DataGrid x:Name="dgViewData2" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" Grid.RowSpan="3" Background="Transparent" Foreground="White" AutoGenerateColumns="False"
    FontSize="18" FontWeight="Medium" BorderThickness="0" HorizontalGridLinesBrush="White" VerticalGridLinesBrush="White" Margin="10" IsHitTestVisible="False" CanUserAddRows="False"
    ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" HeadersVisibility="Column" Visibility="Collapsed"
    GridLinesVisibility="All" CanUserSortColumns="False" IsReadOnly="True">
    <DataGrid.Resources>
        <Style TargetType="DataGrid">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Focusable" Value="False"/>
            <Setter Property="IsHitTestVisible" Value="True"/>
        </Style>
        <Style TargetType="DataGridColumnHeader">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Focusable" Value="False"/>
            <Setter Property="HorizontalAlignment" Value="Right"/>
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="FontSize" Value="20"/>
        </Style>
        <Style TargetType="DataGridRow">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Focusable" Value="False"/>
            <Setter Property="HorizontalAlignment" Value="Right"/>
        </Style>
        <Style TargetType="DataGridCell">
            <Setter Property="HorizontalAlignment" Value="Right"/>
            <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="{x:Null}"/>
                <Setter Property="BorderBrush" Value="{x:Null}"/>
                <Setter Property="Foreground" Value="Transparent"/>
            </Trigger>
        </Style.Triggers>
        </Style>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn Width="150"  Binding="{Binding Identifyer}"/>
        <DataGridTextColumn Width="*"  Binding="{Binding Denomination}"/>
        <DataGridTextColumn Width="*"  Binding="{Binding Quantity}"/>
        <DataGridTextColumn Width="*" Binding="{Binding MaxQuantity}"/>
        <DataGridTextColumn Width="*"  Binding="{Binding TotalValue}"/>
        <!--<DataGridTextColumn Width="*" Binding="{Binding PercentFull}"/>-->
        <DataGridTemplateColumn Width="200" Visibility="Visible">
        <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Grid>
                <ProgressBar Name="pbCash" Width="200" Minimum="{Binding Path=PercentFullMin}" Maximum="{Binding Path=PercentFullMax}" Value="{Binding Path=PercentFull}" Background="Transparent" Foreground="DarkGreen" IsIndeterminate="False"/>
                <TextBlock x:Name="tbProgress" Text="{Binding Path=PercentFullText, StringFormat={}{0}%}"  HorizontalAlignment="Center" VerticalAlignment="Center" Background="Transparent" Foreground="White"/>
            </Grid>
        </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

C#

public List<Recycler_Data> items2 { get; set; } = new List<Recycler_Data>(); //This is being set at the very top of the class.


foreach (var r in data.Recyclers)
{
    foreach (var c in r.Contents)
    {
        //Inserting Column Headers
        dgViewData2.Columns[0].Header = $"{item.Name}";
        dgViewData2.Columns[1].Header = "Value";
        dgViewData2.Columns[2].Header = "Qty";
        dgViewData2.Columns[3].Header = "Max Qty";
        dgViewData2.Columns[4].Header = "Total";
        dgViewData2.Columns[5].Header = "Full";
        string pfTxt = Convert.ToString((Convert.ToDouble(c.Quantity) / Convert.ToDouble(data.Capacity) * 100).ToString("0.00"));
        items2.Add(new Recycler_Data()
        {
            Identifyer = r.Identifyer,
            Denomination = c.Denomination.ToString().Remove(0, 3).Insert(0, " $"),
            Quantity = c.Quantity,
            MaxQuantity = item.Capacity,
            TotalValue = r.TotalValue.ToString().Remove(0, 3).Insert(0, " $"),
            PercentFullText = pfTxt,
            PercentFull = (Convert.ToInt32(c.Quantity) / Convert.ToInt32(data.Capacity) * 100),
            PercentFullMax = 100, 
            PercentFullMin = 0
        });
    }
}
dgViewData2.ItemSource = items2;
public class Recycler_Data
{
    public string Identifyer { get; set; }
    public string Denomination { get; set; }
    public long Quantity { get; set; }
    public object MaxQuantity { get; set; }
    public string TotalValue { get; set; }
    public string PercentFullText { get; set; }
    public int PercentFull { get; set; }
    public int PercentFullMax { get; set; }
    public int PercentFullMin { get; set; }
}

So what I'm expecting is for the progress bar to show whatever number gets passed through PercentFull (obviously within 0 to 100).

1
Recycler_Data needs to implement INotifyPropertyChanged. PercentFull needs to raise the PropertyChanged event, passing its own name nameof(PercentFull) in the event args, when its value changes. That is, if the problem is that you're changing the value of PercentFull after the progress bar is loaded, and you want to see the progress bar's Value changing. It's not clear from your question that PercentFull ever changes after initialization. - 15ee8f99-57ff-4f92-890c-b56153
Bad luck on the two SO questions you found. Also, few WPF tutorials are written by anybody who knows anything about WPF. I usually point people to Rachel Lim's site. Binding to properties of ProgressBar is no different to binding to most other properties, so what you really needed, had you known, was a binding tutorial, not a progressbar tutorial. - 15ee8f99-57ff-4f92-890c-b56153

1 Answers

0
votes

It looks like an integer rounding problem here:

public int PercentFull { get; set;}
PercentFull = (Convert.ToInt32(c.Quantity) / Convert.ToInt32(data.Capacity) * 100);

Say c.Quantity is 2 and data.Capacity is 60. This will say 2/60 which is 0 because the math is done as an int and integer math rounds down by default. Finally, 0 * 100 = 0 thus your result.

You can fix it by using doubles:

public double PercentFull {get; set;}
PercentFull = c.Quantity / Convert.ToDouble(data.Capacity) * 100;

If you want to keep the integer type: (Will have less precision)

public int PercentFull {get; set;}
PercentFull = Convert.ToInt32(c.Quantity) * 100 / Convert.ToInt32(data.Capacity);