2017-01-17 5 views
0

Я хочу сделать что-то очень простое, но мне очень трудно его достичь.Как показать наложение «Загрузка ...», пока модель просмотра перезагружает связанные данные

Предположим, у меня есть контент, связанный с операцией медленной загрузки. Например, наблюдаемый список, который извлекается из локального SQL и занимает несколько секунд. Пока это происходит, я хочу наложить презентацию содержания (например, Groupbox) на текст «Загрузка ...» или любой другой тип «пожалуйста, подождите».

Я быстро пришел к выводу, что просто переключение булевского флага, связанного с пользовательским интерфейсом, до и после операции не работает. Пользовательский интерфейс не обновляется до завершения всей операции. Может быть, потому, что операция интенсивна для процессора, я не знаю.

Теперь я изучаю Adorner, но очень мало информации появляется, и я ищу его в контексте наложения «занятого индикатора». Есть всего несколько решений в Интернете, примерно с 5 лет назад, и я не могу заставить их работать.

Вопрос:

Как просто, как это звучит - как временно показать что-то на экране, в то время как вид Модель работает, чтобы обновить связанные данные?

+0

Спусковой счастливым Mod, который голосует, чтобы закрыть - возможно, этот вопрос настолько тривиально, вы могли бы очень четко описать решение в одном или двух предложениях? –

+0

Был ли флаг boolean атрибутом уведомления?Было ли это свойство, с полем поддержки и тем, которое подняло свойство, изменило уведомления? – Eric

ответ

1

Я быстро пришел к выводу, что просто переключение булевского флага, связанного с пользовательским интерфейсом, до и после операции не работает. Пользовательский интерфейс не обновляется до завершения всей операции. Может быть, потому, что операция интенсивна для процессора, я не знаю.

Да, он должен работать при условии, что вы выполняете длительную операцию на фоновом потоке.

См. Следующий простой пример.

Вид:

<Window x:Class="WpfApplication2.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfApplication2" 
     mc:Ignorable="d" 
     xmlns:s="clr-namespace:System;assembly=mscorlib" 
     Title="Window1" Height="300" Width="300"> 
    <Window.DataContext> 
     <local:Window1ViewModel /> 
    </Window.DataContext> 
    <Window.Resources> 
     <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 
    </Window.Resources> 
    <Grid> 
     <TextBlock>Content...</TextBlock> 
     <Grid Background="Yellow" Visibility="{Binding IsLoading, Converter={StaticResource BooleanToVisibilityConverter}}"> 
      <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Loading...</TextBlock> 
     </Grid> 
    </Grid> 
</Window> 

вид Модель:

public class Window1ViewModel : INotifyPropertyChanged 
{ 
    public Window1ViewModel() 
    { 
     IsLoading = true; 
     //call the long running method on a background thread... 
     Task.Run(() => LongRunningMethod()) 
      .ContinueWith(task => 
      { 
       //and set the IsLoading property back to false back on the UI thread once the task has finished 
       IsLoading = false; 
      }, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); 
    } 

    public void LongRunningMethod() 
    { 
     System.Threading.Thread.Sleep(5000); 
    } 

    private bool _isLoading; 
    public bool IsLoading 
    { 
     get { return _isLoading; } 
     set { _isLoading = value; NotifyPropertyChanged(); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 
1

Вот пример того, как вы можете настроить вид с дисплеем «Загрузка», когда ViewModel \ Model работает над некоторой длинной задачей.

Window

<Window x:Class="Loading.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:Loading" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <local:VisibilityConverter x:Key="visibilityConverter" /> 
</Window.Resources> 
<Window.DataContext> 
    <local:ViewModel x:Name="viewModel" /> 
</Window.DataContext> 
<Grid> 
    <Button Content="Perform" VerticalAlignment="Bottom" HorizontalAlignment="Center" Width="100" Height="30" Command="{Binding HandleRequestCommand}" /> 
    <Border Visibility="{Binding Path=IsLoading,Converter={StaticResource visibilityConverter}}" Background="#AAAAAAAA" Margin="5"> 
     <TextBlock Text="Loading..." VerticalAlignment="Center" HorizontalAlignment="Center" /> 
    </Border> 
</Grid> 

VisibilityConverter.cs (Простой помощник конвертер)

class VisibilityConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return (bool)value ? Visibility.Visible : Visibility.Collapsed; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

ViewModel.cs

public class ViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private bool isLoading; 

    public ViewModel() 
    { 
     HandleRequestCommand = new Command(HandleRequest); 
    } 

    public bool IsLoading 
    { 
     get 
     { 
      return isLoading; 
     } 
     set 
     { 
      if (value != isLoading) 
      { 
       isLoading = value; 
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLoading))); 
      } 
     } 
    } 

    public ICommand HandleRequestCommand 
    { 
     get; 
    } 

    public void HandleRequest() 
    { 
     IsLoading = true; 

     Task.Factory.StartNew(LongRunningOperation); 
    } 

    private void LongRunningOperation() 
    { 
     // *** INSERT LONG RUNNING OPERATION *** 

     Dispatcher.CurrentDispatcher.Invoke(() => IsLoading = false); 
    } 
} 
+0

Просто используйте ProgressRing и привяжите свойство isActive к вашему рабочему свойству viewmodel. Убедитесь, что рабочее свойство имеет уведомление об изменении и событие RaisePropertyChanged. например: IsActive = "{Binding Working}" – SimperT

+0

В основном решение вращается вокруг загрузки данных в отдельную «задачу» и из этой задачи обновляет пользовательский интерфейс через «Dispatcher.CurrentDispatcher», правильно? –