Как обновить индикатор выполнения в DataGrid в WPF?

Я новичок в .Net и хочу знать, как обновить индикатор выполнения, когда я нажимаю кнопку «Загрузить» в определенной строке в DataGrid. Поскольку есть ограниченные источники, посвященные этому, я не понимаю, как этого добиться.

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

Сгенерированный DataGrid выглядит следующим образом:

Метод BeginDownload выглядит следующим образом:

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");
        }
    }

Я только хочу знать, как я могу обновить индикатор прогресса в определенной строке. Например, если я поставлю цикл for и обновлю прогресс с 0 до 100. Как привязать целочисленное значение к индикатору выполнения?

Нашел похожую проблему без ответов -Изменение элемента Wpf Datagrid в той же строке по клику

Каков ваш тип клиентов ... имеет ли он общедоступное свойство Progress? Как вы запускаете Download.. в потоке пользовательского интерфейса или как асинхронную задачу? Вероятно, вам нужно обновить его из метода, который фактически выполняет загрузку.

Anton 19.10.2022 23:17

клиенты являются общедоступным классом, а прогресс является общедоступным свойством. Когда вы нажимаете кнопку «Загрузить», запускается описанный выше метод beginDownload. У меня есть индикатор выполнения для работы. Я опубликую свое решение. Однако мне нужна помощь с замедлением скорости индикатора выполнения. Пожалуйста, помогите с этим

techshot nextgen 20.10.2022 02:38

@Anthon есть решение моей текущей проблемы?

techshot nextgen 20.10.2022 04:55
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
56
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Мое решение в 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;
        }
    }

Класс моих клиентов:

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;
}

У меня есть еще одна проблема: у меня слишком высокая скорость индикатора выполнения. Как замедлить скорость индикатора выполнения?

Ответ принят как подходящий

В WPF очень популярен подход MVVM с шаблоном команды. Соответственно, вам нужно иметь View и ViewModel.. тогда вы сможете использовать команду для кнопки «Загрузить» в своей сетке и передать ей параметр.

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

Для использования DownloadCommand просто привяжите его к свойству 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>

Другие вопросы по теме