Я новичок в .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 в той же строке по клику
клиенты являются общедоступным классом, а прогресс является общедоступным свойством. Когда вы нажимаете кнопку «Загрузить», запускается описанный выше метод beginDownload. У меня есть индикатор выполнения для работы. Я опубликую свое решение. Однако мне нужна помощь с замедлением скорости индикатора выполнения. Пожалуйста, помогите с этим
@Anthon есть решение моей текущей проблемы?





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