Home > database >  How to update the progress bar in DataGrid in WPF?
How to update the progress bar in DataGrid in WPF?

Time:10-21

I am new to .Net and I want to know how I can update the progress bar when I click on the Download Button in a particular row on the DataGrid. Since there's limited sources that address this I don't understand how to achieve this.

 <DataGrid AutoGenerateColumns="False" x:Name="servers" HorizontalAlignment="Center" Height="148" Margin="0,78,0,0" VerticalAlignment="Top" Width="772" PreviewMouseDoubleClick="clientPreview" >
        <DataGrid.Columns>
            <DataGridTextColumn Header="ID" IsReadOnly="True" Binding="{Binding Id}" Width="50"></DataGridTextColumn>
            <DataGridTemplateColumn Header="Progress" 
                                    Width="100">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ProgressBar 
                            Value="{Binding Progress}"
                            Minimum="0" Maximum="100" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Action" Width="100">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate >
                        <Button  Background="#FF00FF35" Click="beginDownload">Download</Button>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

The Generated DataGrid Looks like this :

enter image description here

The BeginDownload Method Looks like this :

private void beginDownload(object sender, RoutedEventArgs e)
    {
        Clients selected = servers.SelectedItem as Clients;
        if (selected != null)
        {
            if (selected.Id == 0)
            {
                MessageBox.Show("Selected Feild is Empty", Title = "Empty Feild Selected");
            }
            else
            {
                //Update Progess Bar and Other Methods

            }
        }
        else
        {
            MessageBox.Show("Selected Field is Empty", Title = "Empty Field Selected");
        }
    }

I only want to know how I can update the progess bar in a particular row. For example if I put a for loop and update the progress from 0 to 100. How to bind the integer value to the progress bar?

Found a Similar problem with no answers -Wpf Datagrid change element in the same row on click

CodePudding user response:

My Solution in Page.xaml.cs:

Visual vis;
private void beginDownload(object sender, RoutedEventArgs e)
{
    Clients selected = servers.SelectedItem as Clients;
    if (selected != null)
    {
        if (selected.Id == 0)
        {
            MessageBox.Show("Selected Feild is Empty", Title = "Empty Feild Selected");
        }
        else
        {
            for (vis = sender as Visual; vis != null; vis = VisualTreeHelper.GetParent(vis) as Visual)
                    if (vis is DataGridRow) //Find current DataGridRow
                    {
                        ProgressChanged();
                        //Other methods
                        break;
                    }
        }
    }
    else
    {
        MessageBox.Show("Selected Field is Empty", Title = "Empty Field Selected");
    }
}
private void ProgressChanged()
    {
        // Update the progressbar percentage 
        for (int i = 0; i <= 100; i  )
        {
            ((Clients)(((DataGridRow)vis).Item)).Progress = i;
        }
    }

My Clients Class :

public class Clients : INotifyPropertyChanged
{
    private int mProgress;
    public Clients()
    {
        Id = 0;
    }

    public int Id { get; set; }

    public int Progress
    {
        get { return mProgress; }
        set
        {
            mProgress = value;
            OnPropertyChanged("Progress");
        }
    }

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

I have one more issue my progress bar speed is too fast, How can I slow down the progress bar speed?

CodePudding user response:

In the WPF very popular MVVM approach with command pattern. Accordingly to it.. you need to have View and ViewModel.. then you will be able to use command for the Download button in your grid and pass parameter to it.

public class ClientsViewModel : INotifyPropertyChanged
{  
   public DelegateCommand DownloadCommand {get; private set;}

   // ctor
   public ClientsVM() 
   {
        DownloadCommand  = new DelegateCommand(DownloadExecute));
   }

   // async method allow to not block UI thread 
   public async void DownloadExecute(object param)
   {
       var client = param as Clients;
       if (client==null) return;

       // TODO: call real code for download 
       for (int i=0; i<100; i  )
       {
          await Task.Delay(100); // slow changes of progress
          client.Progress = i;   // if setter of Progress raised NotifyPropertyChanged.. it will update ProgressBar in your DataGrid
       }      
   }
}

For use your DownloadCommand just bind it to the property of Button

<DataGrid AutoGenerateColumns="False" x:Name="servers" HorizontalAlignment="Center" Height="148" Margin="0,78,0,0" VerticalAlignment="Top" Width="772" PreviewMouseDoubleClick="clientPreview">
        <DataGrid.Columns>
            <DataGridTextColumn Header="ID" IsReadOnly="True" Binding="{Binding Id}" Width="50"></DataGridTextColumn>
            <DataGridTemplateColumn Header="Progress" 
                                    Width="100">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ProgressBar 
                            Value="{Binding Progress}"
                            Minimum="0" Maximum="100" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Action" Width="100">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate >
                        <Button  Background="#FF00FF35" Command="{Binding DownloadCommand, Mode=OneWay}" CommandParameter="{Binding}">Download</Button>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
  • Related