IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Windows 10 UWP开发:模态框进度指示器的实现

    汪宇杰发表于 2016-02-25 02:34:23
    love 0

    Windows 10 Mobile上的文件管理器有这样一个进度指示器,它是一个模态框,不带任何按钮,只有进度条和文本:

    今天我琢磨了很久,绕了一些弯路,发现其实要做一个这样的模态进度指示器很简单。只要用ContentDialog就行。

    平时我们用ContentDialog有些思维定势,就觉得这个对话框一定要提供按钮给用户操作。其实它是可以不设置任何按钮的,这样就有了初步的雏形:

    XAML

    <ContentDialog x:Name="ModalProgressDig">
        <ContentControl.Content>
            <StackPanel Margin="0,10,0,10">
                <ProgressBar IsIndeterminate="True" />
                <TextBlock Text="坐和放宽" TextAlignment="Center" Margin="0,10,0,0" />
            </StackPanel>
        </ContentControl.Content>
    </ContentDialog>
    <Button x:Name="BtnSitAndRelax" Content="坐和放宽" Click="BtnSitAndRelax_OnClick" />

    C#

    private async void BtnSitAndRelax_OnClick(object sender, RoutedEventArgs e)
    {
        // show progress
        await ModalProgressDig.ShowAsync();
    }
    

    之后有2个问题要解决。

    1. 如何在操作完成后关闭这个对话框

    以前是通过用户点击按钮后主动关闭对话框的,就像这样

    var result = await ModalProgressDig.ShowAsync();
    if(result == ...){ // 这时候对话框已经被用户关闭了 }

    现在没有了按钮,我们要从代码里关闭这个对话框。

    关闭对话框的代码是:

    ModalProgressDig.Hide();

    但是不能这样做:

    private async void BtnSitAndRelax_OnClick(object sender, RoutedEventArgs e)
    {
        // show progress
        await ModalProgressDig.ShowAsync();
        
        // do some logic
        await Task.Delay(5000);
        
        // hide progress
        ModalProgressDig.Hide();
    }

    因为你会卡在第一个await上。得等第一个await结束(即用户主动关闭对话框)才会执行后面的逻辑。

    所以要用一个trick:

    private async void BtnSitAndRelax_OnClick(object sender, RoutedEventArgs e)
    {
        // show progress
        var progressTask = ModalProgressDig.ShowAsync();
        
        // do some logic
        await Task.Delay(5000);
        
        // hide progress
        progressTask.Cancel();
        ModalProgressDig.Hide();
    }
    

    现在操作完成后就会自动关闭对话框了。但是我不知道这样写代码会不会有什么问题。

    2. 对话框的样式修改

    以前我们要修改控件的���认样式可以在Blend里右键拷出默认模板编辑,结果这个ContentDialog居然拷不出来。所以要在MSDN上找一个默认模板来改:

    https://msdn.microsoft.com/en-us/library/windows/apps/mt299120.aspx

    我们主要改的就是对话框的高度。从上面的截图对比发现我们自己做的对话框高度明显太高了。

    所以,在这个默认模板里找到:

    <Setter Property="MaxHeight" Value="{ThemeResource ContentDialogMaxHeight}" />
    <Setter Property="MinHeight" Value="{ThemeResource ContentDialogMinHeight}" />

    和Border上的

    MaxHeight="{TemplateBinding MaxHeight}"
    MinHeight="{TemplateBinding MinHeight}" 

    把这对代码删了就好。

    修改后的样式如下(我个人喜好,把Border改成2px了,这个改不改无所谓):

    <Style TargetType="ContentDialog" x:Key="SitAndRelaxDialogStyle">
                <Setter Property="Foreground" Value="{ThemeResource SystemControlPageTextBaseHighBrush}" />
                <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" />
                <Setter Property="HorizontalAlignment" Value="Center" />
                <Setter Property="VerticalAlignment" Value="Top" />
                <Setter Property="IsTabStop" Value="False" />
                <Setter Property="MaxWidth" Value="{ThemeResource ContentDialogMaxWidth}" />
                <Setter Property="MinWidth" Value="{ThemeResource ContentDialogMinWidth}" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ContentDialog">
                            <Border x:Name="Container">
                                <Grid x:Name="LayoutRoot">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto" />
                                    </Grid.RowDefinitions>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto" />
                                    </Grid.ColumnDefinitions>
                                    <Border x:Name="BackgroundElement"
                        Background="{TemplateBinding Background}"
                        FlowDirection="{TemplateBinding FlowDirection}"
                        BorderThickness="2"
                        BorderBrush="{ThemeResource SystemControlForegroundAccentBrush}"
                        MaxWidth="{TemplateBinding MaxWidth}"
                        MinWidth="{TemplateBinding MinWidth}"
                        >
                                        <Grid x:Name="DialogSpace" VerticalAlignment="Stretch">
                                            <Grid.RowDefinitions>
                                                <RowDefinition Height="Auto" />
                                                <RowDefinition Height="*" />
                                                <RowDefinition Height="Auto" />
                                            </Grid.RowDefinitions>
                                            <ScrollViewer x:Name="ContentScrollViewer"
                            HorizontalScrollBarVisibility="Disabled"
                            VerticalScrollBarVisibility="Disabled"
                            ZoomMode="Disabled"
                            Margin="{ThemeResource ContentDialogContentScrollViewerMargin}"
                            IsTabStop="False">
                                                <Grid>
                                                    <Grid.RowDefinitions>
                                                        <RowDefinition Height="Auto" />
                                                        <RowDefinition Height="Auto" />
                                                    </Grid.RowDefinitions>
                                                    <ContentControl x:Name="Title"
                            Margin="{ThemeResource ContentDialogTitleMargin}"
                            Content="{TemplateBinding Title}"
                            ContentTemplate="{TemplateBinding TitleTemplate}"
                            FontSize="20"
                            FontFamily="XamlAutoFontFamily"
                            FontWeight="Normal"
                            Foreground="{TemplateBinding Foreground}"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Top"
                            IsTabStop="False"
                            MaxHeight="{ThemeResource ContentDialogTitleMaxHeight}" >
                                                        <ContentControl.Template>
                                                            <ControlTemplate TargetType="ContentControl">
                                                                <ContentPresenter
                                  Content="{TemplateBinding Content}"
                                  MaxLines="2"
                                  TextWrapping="Wrap"
                                  ContentTemplate="{TemplateBinding ContentTemplate}"
                                  Margin="{TemplateBinding Padding}"
                                  ContentTransitions="{TemplateBinding ContentTransitions}"
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                                                            </ControlTemplate>
                                                        </ContentControl.Template>
                                                    </ContentControl>
                                                    <ContentPresenter x:Name="Content"
                            ContentTemplate="{TemplateBinding ContentTemplate}"
                            Content="{TemplateBinding Content}"
                            FontSize="{ThemeResource ControlContentThemeFontSize}"
                            FontFamily="{ThemeResource ContentControlThemeFontFamily}"
                            Margin="{ThemeResource ContentDialogContentMargin}"
                            Foreground="{TemplateBinding Foreground}"
                            Grid.Row="1"
                            TextWrapping="Wrap" />
                                                </Grid>
                                            </ScrollViewer>
                                            <Grid x:Name="CommandSpace" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition/>
                                                    <ColumnDefinition/>
                                                </Grid.ColumnDefinitions>
                                                <Border x:Name="Button1Host"
                          Margin="{ThemeResource ContentDialogButton1HostMargin}"
                          MinWidth="{ThemeResource ContentDialogButtonMinWidth}"
                          MaxWidth="{ThemeResource ContentDialogButtonMaxWidth}"
                          Height="{ThemeResource ContentDialogButtonHeight}"
                          HorizontalAlignment="Stretch" />
                                                <Border x:Name="Button2Host"
                          Margin="{ThemeResource ContentDialogButton2HostMargin}"
                          MinWidth="{ThemeResource ContentDialogButtonMinWidth}"
                          MaxWidth="{ThemeResource ContentDialogButtonMaxWidth}"
                          Height="{ThemeResource ContentDialogButtonHeight}"
                          Grid.Column="1"
                          HorizontalAlignment="Stretch" />
                                            </Grid>
                                        </Grid>
                                    </Border>
                                </Grid>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

    然后在我们的对话框上引用这个样式:

    <ContentDialog x:Name="ModalProgressDig" Style="{StaticResource SitAndRelaxDialogStyle}">

    大功告成:



沪ICP备19023445号-2号
友情链接