如何显示'正在加载...'视图模型重新加载绑定数据时覆盖

时间:2017-01-17 22:03:07

标签: wpf xaml adorner

我想做一些听起来非常简单的事情,但我觉得很难实现。

假设我有一些内容与慢速加载操作绑定。例如,一个可观察的列表,从本地SQL中检索并需要几秒钟。在发生这种情况时,我希望将内容展示器(例如Groupbox)与"正在加载..."文字或任何其他“请等待”#39;内容类型。

我很快得出结论,在操作之前和之后简单地切换绑定到UI的布尔标志并不起作用。在整个操作完成之前,UI不会刷新。也许是因为操作是CPU密集型的,我不知道。

我现在正在研究Adorner,但是我在“繁忙指标”的背景下搜索它的信息非常少。覆盖。从大约5年前开始,互联网上只有一些解决方案,我无法使用它们。

问题:

听起来很简单 - 如何在屏幕上暂时显示某些内容,而View Model正在努力更新绑定数据?

2 个答案:

答案 0 :(得分:2)

  

我很快得出结论,在操作之前和之后简单地切换绑定到UI的布尔标志并不起作用。在整个操作完成之前,UI不会刷新。也许是因为操作是CPU密集型的,我不知道。

是的,如果您实际在后台线程上执行长时间运行的操作,它应该可以工作。

请参阅以下简单示例。

查看:

<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 :(得分:1)

以下是在ViewModel \ Model处理某项长任务时如何使用“正在加载”显示设置视图的示例。

<强>窗口

div.panel:hover {
  border: 1px solid grey;
  /*I want the panel-heading to be grey*/
}
.panel-default > .panel-heading {
  background-color: #16749F;
  color: #ddd;
}
.panel-default > .panel-heading:hover {
  background-color: grey;
}

VisibilityConverter.cs (简单助手转换器)

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

<强> ViewModel.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();
    }
}