У меня есть приложение WPF, которое имеет DataGrid
, которое привязано к ObservableCollection<string>
с именем «Клиенты» , и у меня также есть кнопка, которая связана с командой, которая запускает что-тотяжелая задачаон имитирует добавление нескольких записей в DataGrid
как можно быстрее.
Проблема, с которой я сталкиваюсь, заключается в том, что при добавлении записей в DataGrid
при попытке запуска возникают заикания, а иногда и тупики.для перемещения пользовательского интерфейса при добавлении записей в DataGrid
.
Насколько я понимаю, это потому, что я обновляю DataGrid
в потоке пользовательского интерфейса, используя Application.Current.Dispatcher.Invoke(() => { /*Update OC*/ });
, и даже если они могут быть маленькимиобновляет пользовательский интерфейс, многие из них могут вызвать заикание, теперь это мое понимание, и я могу быть совершенно не прав.
Мой вопрос ... Есть ли способ сделать этот асинхронный или уменьшить заикание/ deadlocks каким-либо другим способом?
Пользовательский интерфейс XAML
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<DataGrid ItemsSource="{Binding Customers}" AutoGenerateColumns="False"
Width="300" Height="200">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Image" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding }" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button Width="100"
Height="25"
Content="Start"
Command="{Binding StartAddingCommand}"/>
</StackPanel>
<Border VerticalAlignment="Bottom"
Height="25" Background="Orange">
<TextBlock Text="{Binding Customers.Count}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</Grid>
MainViewModel
class MainViewModel : ObservableObject
{
public ObservableCollection<string> Customers { get; set; }
public RelayCommand StartAddingCommand { get; set; }
public MainViewModel()
{
Customers = new ObservableCollection<string>();
StartAddingCommand = new RelayCommand(o => AddCustomers(), o => true);
}
private void AddCustomers()
{
Task.Run(() =>
{
try
{
foreach (var VARIABLE in GetHTML("https://pastebin.com/raw/gG540TEj"))
{
Application.Current.Dispatcher.Invoke(() =>
{
Customers.Add(VARIABLE.ToString());
});
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}
public string GetHTML(string page)
{
WebClient client = new WebClient();
return client.DownloadString(page);
}
}
А RelayCommand & ObservableObject являются просто общими.
RelayCommand
public class RelayCommand : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
}
ObservableObject
class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}