zoukankan      html  css  js  c++  java
  • Windows App开发之常用控件与应用栏

    控件的属性、事件与样式资源

    如何添加控件

    添加控件的方式有多种,大家更喜欢下面哪一种呢?

    1)使用诸如Blend for Visual Studio或Microsoft Visual Studio XAML设计器的设计工具。
    2)在Visual Studio XAML编辑器中将控件添加到XAML代码中。
    3)在代码中添加控件。 注意:当应用运行时会看到你在代码中添加的控件,但在 Visual Studio XAML 设计器中看不到。

    前面我们通过在工具箱拖住控件以及直接在写XAML代码来设置控件,在教程的后面,我们会看到在C#后台代码中添加控件。Blend我们暂时还没有用到,不过其在绘制图形和动画上可谓非常强大和优秀。

    设置控件的属性

    控件的属性相比大家都已经会用了,一来可以直接在XAML中添加属性,二来可以在属性视图中添加和修改属性。

    这里写图片描述

    为控件添加事件

    如果要添加和修改事件呢,同样在属性视图中,点击右上角的闪电图标即可。如果要添加Click事件,那么在Click的输入框中输入好事件名称后直接按Enter即可。此时VS就会自动跳转到C#后台代码中,第一个参数sender是对处理程序所附加的对象的应用,第二参数是事件数据,它通常在签名中显示为e参数。

    private void btnSetStyle_Click(object sender, RoutedEventArgs e)
    {
        Button b = (Button)sender;
        b.Height = 400;
        b.Width = 320;
    }

    上面的这段代码这会将所点击的Button的高设置为400,宽设置为320;除了这种方式外,也可以按如下操作,其中btnSetStyle是当前Button的名字:

    private void btnSetStyle_Click(object sender, RoutedEventArgs e)
    {
        btnSetStyle.Height = 400;
        btnSetStyle.Width = 320;
    }

    除此之外,我们也可以不在XAML中定义Click事件,按照如下操作也可以达到相同的效果,它会将两个事件相互关联。

    public MainPage()
    {
         this.InitializeComponent();
    
         btnSetStyle.Click += new RoutedEventHandler(btnSetStyle_Click);
    }
    
    private void btnSetStyle_Click(object sender, RoutedEventArgs e)
    {
        btnSetStyle.Height = 400;
        btnSetStyle.Width = 320;
    }
    

    为控件设置样式资源

    即便没有添加过资源,也不清楚什么是样式,没关系,想必大家都玩过2048吧。游戏中有许多方格,那这些方格的样式会不会一个个去定义呢,当然不是,可以直接用样式资源来定位到所有的Button。

    以下是一个基本样式,

    <Page.Resources>
       <Style TargetType="Button">
          <Setter Property="FontWeight" Value="Bold"/>
          <Setter Property="FontSize" Value="40"/>
          <Setter Property="HorizontalAlignment" Value="Center"></Setter>
          <Setter Property="VerticalAlignment" Value="Center"></Setter>
          <Setter Property="Background" Value="Gray"></Setter>
          <Setter Property="Width" Value="100"></Setter>
          <Setter Property="Height" Value="100"></Setter>
          <Setter Property="Template">
              <Setter.Value>
                  <ControlTemplate TargetType="Button">
                      <Grid x:Name="Grid" Background="Transparent">
                          <Border x:Name="Border" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Background="{TemplateBinding Background}" >
                              <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="Center"  VerticalAlignment="Center"/>
                           </Border>
                       </Grid>
                   </ControlTemplate>
               </Setter.Value>
           </Setter>
        </Style>
    </Page.Resources>

    但是这里也有一个问题,如果我们有10个Button控件,却只想其中8个用到这些定义,另外2个想用另一种控件,那该怎么办呢?

    将样式定义为资源,其实是有2中方式的。

    一种就是直接用Style的TargetType属性来定义到所有的目标控件。

    另一种则除了用TargetType属性外,还可以用x:key属性,然后再具体的控件中庸显式的关键字StaticResource来设置具体的Style属性。

    <Page.Resources>     
         <Style TargetType="Button">              
             <Setter Property="FontStyle" Value="Oblique" />
             <Setter Property="FontSize" Value="20" />
             <Setter Property="BorderBrush" Value="Green" />
             <Setter Property="BorderThickness" Value="5" />
             <Setter Property="Foreground" Value="Orange" />
             <Setter Property="Height" Value="80"/>
             <Setter Property="Width" Value="160"/>
         </Style>
    
         <Style x:Key="OtherStyle" TargetType="Button">
             <Setter Property="FontStyle" Value="Italic" />
             <Setter Property="FontSize" Value="16" />
             <Setter Property="Foreground" Value="Lavender" />
             <Setter Property="Height" Value="160"/>
             <Setter Property="Width" Value="320"/>
             <Setter Property="Opacity" Value="0.2"/>
         </Style>                                                            
    </Page.Resources>

    具体效果见下图,其中Opacity属性为透明度。

    这里写图片描述

    大家都知道类可以继承,样式也是可以继承的。

    部分控件介绍

    通过前面的学习,已经见过一些控件了,现在起将逐步见到更多控件。但由于控件太多,教程中无法一一介绍,请自行举一反三。教程内容也将不断更新。

    Button

    前面最常用的控件就是Button了,Button还有一个有意思的属性,当把鼠标指针放在Button上时,就会在Button的头顶冒出一串文本。

    <Button ToolTipService.ToolTip="Go to www.blog.csdn.net/nomasp" Margin="692,458,0,230"/>

    Button有一个很有意思的属性。

    <Button Content="摩天轮" Margin="134,363,0,367">               
        <ToolTipService.ToolTip>
            <Image MaxHeight="80" MaxWidth="100" Source="Assets/343219.jpg"/>       
        </ToolTipService.ToolTip>     
    </Button>

    只要把鼠标放到Button上面就会显示出这张图片了,也叫做帮助提示吧。其实更简单的方法是下面这种。它显示的是一个后退的样式,而且鼠标放上去会有文字Back提示。

    <Button Content="摩天轮" ToolTipService.ToolTip="Back"
                    Style="{StaticResource NavigationBackButtonNormalStyle}" />  

    ToggleSwitch

    这个控件和Button很像,它像开关一样。

    <ToggleSwitch x:Name="toggleSwitch1" Header="NoMasp Toggle" 
          OnContent="On" OffContent="Off" Toggled="ToggleSwitch_Toggled" 
          Margin="409,468,0,227"/>
    
    <ToggleSwitch x:Name="toggleSwitch2" Header="NoMasp Toggle" 
         OnContent="On" OffContent="Off" IsOn="True" 
         Toggled="ToggleSwitch_Toggled" Margin="409,565,0,130"/>
    

    这里写图片描述

    MessageDialog

    这控件和Button一起讲还蛮合适的,我们随意添加一个Button,然后写好Click事件如下。

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        Windows.UI.Popups.MessageDialog messageDialog =
            new Windows.UI.Popups.MessageDialog("噢,你刚刚踩到了地雷!");
        await messageDialog.ShowAsync();
    }

    注意要在函数上加上async表示异步。

    这里写图片描述

    如果需要预览效果,可以参见教程随后的“用浮出控件做预览效果”。

    ComboBox

    ComboBox提供了下拉列表,自然也是一个很常用的控件。

    <ComboBox Height="50" Width="200" Name="cbox1"  SelectionChanged="cbox1_SelectionChanged" Margin="17,47,1049,671">
         <x:String>Select 1</x:String>
         <x:String>Select 2</x:String>
         <x:String>Select 3</x:String>
         <x:String>Select 4</x:String>
    </ComboBox>

    这里写图片描述

    这里写图片描述

    ListBox

    ListBox控件和ComboBox很相似,都可以让用户选择已经嵌入在列表中的选项。用法如下:

    <ListBox x:Name="listBox1" SelectionChanged="listBox1_SelectionChanged" Width="100">
        <x:String>Item 1</x:String>
        <x:String>Item 2</x:String>
        <x:String>Item 3</x:String>
    </ListBox>

    DatePicker、TimePicker

    Winows平台设置时间的控件倒是很有特色,就是DatePicker和TimePicker。

    <DatePicker Foreground="Red" Header="NoMasp Date" Margin="3,177,0,533"/>
    <TimePicker Foreground="Green" Header="NoMasp Time" Margin="3,246,0,464" Width="289"/>    

    以下既是截图,也是写这篇教程的时间。
    这里写图片描述

    这个控件的更多介绍也在教程随后的“时间控件的更多介绍”中。

    FlipView

    FlipView是一个可以让用户逐个浏览的项目集合的控件,下面是相关的示例代码。CommonAssets文件夹完全可以定义在Shared目录下,这样WP也可以拿来用了。

    <FlipView>
        <Image Source="CommonAssets/5083.jpg"/>
        <Image Source="CommonAssets/5503.jpg"/>
        <Image Source="CommonAssets/6121.jpg"/>
    </FlipView>

    这里写图片描述

    除此之外呢,我们还可以在后台代码中添加,下面的第二段代码和第一段类似,不过是用的List。

    FlipView flipView = new FlipView();
    flipView.Items.Add("Item 1");
    flipView.Items.Add("Item 2");
    flipView.SelectionChanged += filpView_SelectionChanged;
    grid1.Children.Add(flipView);
    List<String> listItems = new List<string>();
    listItems.Add("Item 1");
    listItems.Add("Item 2");                                                                                                       
    FlipView flipView = new FlipView();
    flipView.ItemsSource = listItems;
    flipView.SelectionChanged += filpView_SelectionChanged;          
    grid1.Children.Add(flipView);

    除了这2种方式之外呢,用CollectionViewSource来绑定数据也是完全没问题的。

    <Page.Resources>   
        <CollectionViewSource x:Name="collectionVSFlipView" Source="{Binding Items}"/>
    </Page.Resources>

    上面是一段资源文件,然后FlipView ListView的ItemsSource添加静态资源绑定就OK了。

    <FlipView x:Name="flipView" 
              ItemsSource="{Binding Source={StaticResource collectionVSFlipView}}"/>

    如果大家自己试过FlipView就会发现它的图片资源等都是左右滚动的,如果要用上下滚动呢?那就用下面这个ItemsPanelTemplate模板就好了。

    <FlipView.ItemsPanel>
         <ItemsPanelTemplate>
              <VirtualizingStackPanel Orientation="Vertical"/>
         </ItemsPanelTemplate>
    </FlipView.ItemsPanel>

    ScrollBar

    如果有缩放图片,并且可以滚动以查看图片的需要,那么就可以用ScrollBar啦。这主要是能留给图片的位置太小以至于图片无法全部显示出来。

    <ScrollViewer ZoomMode="Enabled" MaxZoomFactor="12" HorizontalScrollMode="Enabled" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" VerticalScrollMode="Enabled" Height="200" Width="200" Margin="363,35,803,533">
    
        <Image Source="CommonAssets/6121.jpg" Height="400" Width="400"/> 
    </ScrollViewer>

    这里写图片描述

    Viewbox

    还有一个控件则可以将图片等缩放到指定的大小的,那就是Viewbox。大家看看下面这个图,是不是很炫酷呢。

        <Viewbox MaxHeight="33" MaxWidth="33" Margin="23.5,35,-26,-35">
                <Image Source="CommonAssets/5503.jpg" Opacity="0.9 "/>
            </Viewbox>
            <Viewbox MaxHeight="66" MaxWidth="66" Margin="26,35,-26,-35">
                <Image Source="CommonAssets/5503.jpg" Opacity="0.6"/>
            </Viewbox>
            <Viewbox MaxHeight="99" MaxWidth="99" Margin="26,35,-26,-35">
                <Image Source="CommonAssets/5503.jpg" Opacity="0.3"/>
            </Viewbox>

    这里写图片描述

    GridView

    相信大家都已经看过了GridView控件,很多Modern应用都会采用的。其和ComboBox挺类似的。

    <GridView x:Name="gView1" SelectionChanged="gView1_SelectionChanged">
        <x:String>Item 1</x:String>
        <x:String>Item 2</x:String>
        <x:String>Item 3</x:String>
    </GridView>

    HyperlinkButton

    HyperlinkButton既可以作为Button来用,也可以用来做超链接。

    <HyperlinkButton Content="NoMasp--CSDN" NavigateUri="http://blog.csdn.net/nomasp" />

    ProgressBar

    相信大家都挺喜欢玩进度条的吧?我本人倒是觉得相比于Win7及Vista等,Win8的进度条变得更加有意思了。

    <ProgressBar x:Name="progressBar1" IsIndeterminate="True" Width="100" Margin="607,377,659,385"/>
    <ProgressBar x:Name="progressBar2" Value="70 " Width="100" Margin="607,352,659,410"/>
    

    第一个图是运行中的进度条啦;第二个图中的上图也就是progressBar1,其Value为70的确定进度的进度条,下图则是progressBar2,是运行中的进度条在设计器中的静止状态。

    这里写图片描述

    ProgressRing

    环形的进度条会不会更好玩呢?

    <ProgressRing x:Name="progressRing1" IsActive="True" />

    这里写图片描述

    Slider

    比如说win8上的音量呀、屏幕亮度呀,这些地方都用到了滑动条。这里来看看它的ThumbToolTipValueConverter属性吧。为了将值绑定到Slider上,我们需要有一个类,这个类需要一个为数据绑定提供值转换的接口。可视化元素也就是Slider为绑定目标,其有2个方向:数据源->数据->绑定目标,绑定目标->数据->数据源。

    我们需要写一个类,可以直接在MainPage.xaml.cs下写,但更好是单独新建一个类,再考虑到这个是通用应用,所以将类新建到Shared下比较合适。

    public class ThumbToolTipValueConverter : Windows.UI.Xaml.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if(value is double)
            {
                    double dValue= System.Convert.ToDouble(value);
                    return dValue;                
            }
            return null;
         }
    
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            return null;
        }
    }

    然后添加以下代码作为本地实例化的资源即可。

    <Page.Resources>
       <local:ThumbToolTipValueConverter x:Key="thumbToolTipValueC"/>
    </Page.Resources>

    最后就是传说中的本体啦。

    <Slider Width="200" Height="50" Name="slider1"    
          ThumbToolTipValueConverter="{StaticResource thumbToolTipValueC}" />

    这里写图片描述

    我们还可以添加一个Button和TextBlock,让点击来在TextBlock上显示Slider的Value。

    private void btnGetSliderValue_Click(object sender, RoutedEventArgs e)
    {
        tblockSlider.Text = slider1.Value.ToString();
    }

    这里写图片描述

    用浮出控件做预览效果

    在前面学习控件的时候,我们已经见过了MessageDialog了,关于Button还有一个浮出控件Flyout哦。具体是怎样用呢?接下来就一起看看。

    我们还是延续前面的那个示例好了,那么,代码来了。

            <Button x:Name="btnWhat" Content="这是什么?">
                <Button.Flyout>
                    <Flyout>
                        <StackPanel>
                            <TextBlock Width="430" Style="{StaticResource BaseTextBlockStyle}"
                                       Text="噢!你刚刚又踩到地雷了,要撤销吗?" Foreground="Red" FontSize="25"/>
                            <Button Click="btnUndo_Click" Margin="12" Content="撤销"/>
                        </StackPanel>
                    </Flyout>
                </Button.Flyout>
            </Button>

    当我们点击了撤销按钮后,当然需要btnWhat按钮的Flyout消失掉,这个嘛,也只要1行代码啦。另外这个踩雷的逻辑这里就不展开啦.

    private void btnUndo_Click(object sender, RoutedEventArgs e)
    {
         btnWhat.Flyout.Hide();
    }

    更为重要的是在于这些在WP8上也是通用的,这才是核心所在。既然这一篇教程主要是浮出控件,如果可以借助浮出产生预览图像的效果会不会很棒呢?先来看张运行截图吧。

    这里写图片描述

    以下都是代码啦,什么Binding呀之类的都不用管啦。需要注意的地方也就是那些Height和Width可能需要拿来调整一下。

       <Page.Resources>
            <Flyout x:Key="ResourceFlyoutImage" Placement="Right">                            
                <Image Source="{Binding Path=Source}" MaxHeight="800" MaxWidth="1400" Stretch="Uniform"/>
                <Flyout.FlyoutPresenterStyle>
                    <Style TargetType="FlyoutPresenter">
                        <Setter Property="MinHeight" Value="900"/>
                        <Setter Property="MinWidth"  Value="1600"/>
                        <Setter Property="BorderThickness" Value="3"/>
                        <Setter Property="Background" Value="Wheat"/>
                        <Setter Property="BorderBrush" Value="Green"/>
                        <Setter Property="ScrollViewer.ZoomMode" Value="Enabled"/>        
                    </Style>
                </Flyout.FlyoutPresenterStyle>
            </Flyout>
        </Page.Resources>    
    
        <Grid>
            <StackPanel HorizontalAlignment="Left" Orientation="Vertical">
                <Image Source="Assets/14152.jpg" Width="100" Height="100" Margin="12" Tapped="img_Tapped"  
                       FlyoutBase.AttachedFlyout="{StaticResource ResourceFlyoutImage}"                        
                       DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
    
                <Image Source="Assets/14158.jpg" Width="100" Height="100" Margin="12" Tapped="img_Tapped"  
                       FlyoutBase.AttachedFlyout="{StaticResource ResourceFlyoutImage}"                                                 
                       DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
    
                <Image Source="Assets/14160.jpg" Width="100" Height="100" Margin="12" Tapped="img_Tapped"    
                       FlyoutBase.AttachedFlyout="{StaticResource ResourceFlyoutImage}"                           
                       DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
    
                <Image Source="Assets/14164.jpg" Width="100" Height="100" Margin="12" Tapped="img_Tapped"      
                       FlyoutBase.AttachedFlyout="{StaticResource ResourceFlyoutImage}"                                                  
                       DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
            </StackPanel>
        </Grid>
    private void img_Tapped(object sender, TappedRoutedEventArgs e)
    {
        FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender);
    }             

    同样的,在WP上也是可以得哦,一下是做了些修改后的XAML代码啦。正如大家所见,我把图片都缩小了,Placement也设置成了Top,StactPanel的属性也做了修改。

        <Page.Resources>
            <Flyout x:Key="ResourceFlyoutImage" Placement="Top">
                <Image Source="{Binding Path=Source}" MaxHeight="600" MaxWidth="400" Stretch="Uniform"/>
                <Flyout.FlyoutPresenterStyle>
                    <Style TargetType="FlyoutPresenter">
                        <Setter Property="MinHeight" Value="600"/>
                        <Setter Property="MinWidth"  Value="400"/>
                        <Setter Property="BorderThickness" Value="3"/>
                        <Setter Property="Background" Value="Wheat"/>
                        <Setter Property="BorderBrush" Value="Green"/>
                        <Setter Property="ScrollViewer.ZoomMode" Value="Enabled"/>
                    </Style>
                </Flyout.FlyoutPresenterStyle>
            </Flyout>
        </Page.Resources>
    
        <Grid>
            <StackPanel VerticalAlignment="Bottom" Orientation="Horizontal">
                <Image Source="Assets/14152.jpg" Width="72" Height="60" Margin="12" Tapped="img_Tapped"  
                       FlyoutBase.AttachedFlyout="{StaticResource ResourceFlyoutImage}"                        
                       DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
    
                <Image Source="Assets/14158.jpg" Width="72" Height="60" Margin="12" Tapped="img_Tapped"  
                       FlyoutBase.AttachedFlyout="{StaticResource ResourceFlyoutImage}"                                                 
                       DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
    
                <Image Source="Assets/14160.jpg" Width="72" Height="60" Margin="12" Tapped="img_Tapped"    
                       FlyoutBase.AttachedFlyout="{StaticResource ResourceFlyoutImage}"                           
                       DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
    
                <Image Source="Assets/14164.jpg" Width="72" Height="60" Margin="12" Tapped="img_Tapped"      
                       FlyoutBase.AttachedFlyout="{StaticResource ResourceFlyoutImage}"                                                  
                       DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}"/>
            </StackPanel>
        </Grid>

    看样子效果还不错嘛。

    这里写图片描述

    这里写图片描述

    这里写图片描述

    时间控件的更多介绍

    在前面我们走马观花地介绍了一大堆控件,其中自然也包括这DatePicker和TimePicker,那么稍微高级些的用法呢?

    如果你想做一个关于健身、闹钟等的App,那么不可避免的会用到时间这些控件了。

    <DatePicker x:Name="datePicker" Header="NoMasp Date" Foreground="Beige"/>          
    <Button x:Name="btnOK" Click="btnOK_Click" Content="确定" Foreground="Cyan" Margin= "292,378,0,352" >
         <Button.Flyout>
              <Flyout>
                  <TextBlock x:Name="tblock1" Foreground="Fuchsia"/>
              </Flyout>
         </Button.Flyout>
    </Button>

    那么我们可能需要所选定的时间是未来时间,也就是比应用运行时的时间要大。获取当前选中的时间给程序的其他部分使用也是很简单的,我这里的year等都在之前定义过了哦,在函数内定义可是不明智的哟。

    private void btnOK_Click(object sender, RoutedEventArgs e)
    {
        if(datePicker.Date>DateTimeOffset.Now)
            tblock1.Text = string.Format("你所选中的时间是:{0}。", datePicker.Date.ToString("D"));
        else
            tblock1.Text = "噢!你想要穿越吗?";
    
        year = datePicker.Date.Year;
        month = datePicker.Date.Month;
        day = datePicker.Date.Day;   
    }        

    有意思的事情又来了,如果你是想要做一个时间囊,默认的时间就是10年之后,那么DatePicker的初始事件如果正好就是10年后不是非常好吗。那么我们要做的呢,首先就是给DatePicker的Loaded写一条事件啦。(虽然我觉得App是保存不了10年的)

    private void datePicker_Loaded(object sender, RoutedEventArgs e)
    {
        datePicker.Date = DateTimeOffset.Now.AddYears(10);
    }

    如果不想兴师动众去用DatePicker的Loaded,那么也可以直接在后台代码中这样写。

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        datePicker.Date = DateTimeOffset.Now.AddYears(10);
    }

    我还做了一个小测试呢,在Loaded事件中让时间增加11年,在OnNavigatedTo事件中让时间增加10年,结果——结果是增加了11年啦,看来还是自家的Loaded更厉害。

    接下来就是TimePicker啦,回到健身的话题,假设哈,6点到18点才适合运动,那么我们的Microsoft Band就做了以下这么个要求(开玩笑啦)。

        private void btnOK_Click(object sender, RoutedEventArgs e)
            {
                TimeSpan startTime = new TimeSpan(6, 0, 0);
                TimeSpan endTime = new TimeSpan(18, 0, 0);
    
                if(timePicker.Time>=startTime&&timePicker.Time<=endTime)
                {
                    tblock1.Text = string.Format("这段时间运动都是很好的哦——{0}。", timePicker.Time.ToString());
                }
                else
                {
                    tblock1.Text = "此时间吧不适合运动的吧?";
                }       
            }        

    也许你还想控制手环上时间选择器的初始时间,那么代码来了。

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {                                              
         timePicker.Time = new TimeSpan(23, 0, 0);
    }

    作为强迫症患者呢,每次我设定闹钟的时候都要设置在一个比较好的时间,比如被5整除啦、质数啦。这里可以用MinuteIncrement属性来控制分钟的增量哟,比如增量为5呀。从小学起就飞得把电子手表的时间给设置成24小时制的,这个也是可以实现的,ClockIdentifier设置成24HourClock就搞定啦。

    应用栏

    基本的用法我们在教程前面的“页面布局与基本导航”中已经讲过了,这里继续补充关于应用栏的更多用法。

    Icon

    在之前的学习中,我们知道Icon属性中有很多很多系统预定义,但也许这些还是不够的,现在就来增加几种用法。

    字符集应用

    <AppBarToggleButton Label="Sigma" Click="AppBarButton_Click">
        <AppBarToggleButton.Icon>
            <FontIcon Glyph="&#x03A3;"/>
        </AppBarToggleButton.Icon>
    </AppBarToggleButton>

    关于更多字符集的应用请访问维基百科。

    PathIcon

    我们也可以用路径来绘制一个属于自己的图形哦,下面的图形大概就是9点钟的样子啦。

    <AppBarToggleButton Label="Time" Click="AppBarButton_Click">
        <AppBarToggleButton.Icon>                              
            <PathIcon Data="F1 M 20,20 21,1L 21,21L 8,21"/>
        </AppBarToggleButton.Icon>
    </AppBarToggleButton>

    这里写图片描述

    如何适应不同的分辨率

    如何适应不同的分辨率这也是值得我们去解决的问题,毕竟不论是从8英寸的平板还是25英寸的台式机,甚至还有4英寸至7英寸的手机,在应用栏按钮太多而屏幕不够大时,多余的按钮该怎么办呢?

    默认情况下,应用栏图标的宽度都是确定好的100像素哦。那么我们先来看两张图片好了,由于Windows 10是可以直接调整Modern应用的大小的(而不是windows 8那种只能全屏显示),所以我直接拉伸Modern大小以模拟分辨率的概率啦。

    这里写图片描述

    这里写图片描述

        <Page.BottomAppBar>
            <AppBar x:Name="bottomAppBar" IsSticky="True">
                <Grid>          
                    <StackPanel x:Name="leftBottomAppBar" 
                                Orientation="Horizontal">
                        <AppBarButton Label="Like" Icon="Like"/>
                        <AppBarButton Label="Dislike" Icon="Dislike"/>
                        <AppBarButton Label="Delete" Icon="Delete"/>
                        <AppBarButton Label="Download" Icon="Download"/>
                        <AppBarButton Label="Pin" Icon="Pin"/>
                    </StackPanel>
                    <StackPanel x:Name="rightBottomAppBar" 
                            Orientation="Horizontal" HorizontalAlignment="Right">
                        <AppBarButton Label="Play" Icon="Play"/>
                        <AppBarButton Label="Pause" Icon="Pause"/>
                        <AppBarButton Label="Stop" Icon="Stop"/>
                        <AppBarButton Label="Previous" Icon="Previous"/>
                        <AppBarButton Label="Next" Icon="Next"/>
                    </StackPanel>
                </Grid>
            </AppBar>
        </Page.BottomAppBar>

    这里为了调试更加方便,所以使用了IsSticky属性。AppBarButton还有一个很重要的属性哟,之前用不到,不过这里就是核心成员了呢,它就是IsCompact。这个属性可以让应用栏按钮只显示图标而不显示文字,也就是Label啦。那么我们的工作就要围绕这个属性来展开了。

    我们可以这样假设,有一个函数,它有一个布尔变量的参数,参数为真的话呢,那么所有的这些AppBarButton的IsCompact属性也为真。在以下这段代码中,我们先将bottomAppBar的自对象选取为root,这样一来的话呢,如果应用中还有顶部的应用栏,就不会相互干扰啦。然后逐步取出root和panel中的自对象就好咯。

         private void AppBarButtonCompact(bool isCompact)
            {
                Panel root = bottomAppBar.Content as Panel;
                if(root!=null)
                {
                    foreach(Panel panel in root.Children)
                    {
                        foreach (ICommandBarElement child in panel.Children)
                        {
                            child.IsCompact = isCompact;
                        }
                    }
                }
            }

    接下来还需要判断到底需不需要启用IsCompact,那这又是由什么决定的呢,既然前面提到是因为屏幕的分辨率,也就是所应用所占用的宽度会导致应用栏发生重叠,那么答案就毫无疑问了。看到下面的代码相信大家都明白了,至于为何是宽度的界限在1000呢,那是因为有10个AppBarButton,前面也说了它们的宽度是100。(不带Label的话呢,就只需要60像素啦。)

         void AppSizeChanged(object sender, SizeChangedEventArgs e)
            {
                if (e.NewSize.Width != e.PreviousSize.Width)
                {
                    if (e.NewSize.Width < 1000)
                    {
                        AppBarButtonCompact(true);
                    }
                    else
                    {
                        AppBarButtonCompact(false);
                    }
                }
            }

    来张图片以示搞定这个问题了吧。

    这里写图片描述

    但是像我这么钻牛角尖的人,10个AppBarButton用这种方式搞定了,那20个呢?我们就来演示一下,把之前XAML中的AppBarButton复制粘贴一番。如果是2K、4K的屏幕应对20个没问题啊,但我这1920X1080的屏幕就放不下了。

    这里写图片描述

    那么这又有什么办法可以解决的吗?当然有啦,将这20个图标切成2列就好啦。我们首先在Grid中添加一行。

    <Grid.RowDefinitions>      
        <RowDefinition Height="auto"/>                     
        <RowDefinition Height="auto"/>                
    </Grid.RowDefinitions>

    再通过下面这张方式来调整它处于哪一行,以及在水平方向的右侧还是左侧。这里我将两行都设置在右侧啦。

    leftBottomAppBar.SetValue(Grid.RowProperty, 1);
    leftBottomAppBar.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Right);           

    当然了,这样一来就可以放40个AppBarButton啦,如果缩小应用的大小的话为了容纳更多还可以用IsCompact属性呢。不过没有哪个应用做成这样吧。

    这里写图片描述

    另外呢,如果把应用栏设计成这样的话。

    <Page.BottomAppBar>   
       <AppBar x:Name="bottomAppBar" IsSticky="True">            
          <Grid>                
             <Grid.ColumnDefinitions>                      
                 <ColumnDefinition Width="*"/>                    
                 <ColumnDefinition Width="*"/>                
             </Grid.ColumnDefinitions>               
             <StackPanel Grid.Column="0" x:Name="leftBottomAppBar"  Orientation="Horizontal" HorizontalAlignment="Left">                                     
                 <AppBarButton Label="Like" Icon="Like"/>                
                 <AppBarButton Label="Dislike" Icon="Dislike"/>           
                 <AppBarButton Label="Delete" Icon="Delete"/>                 
                 <AppBarButton Label="Download" Icon="Download"/>       
                 <AppBarButton Label="Pin" Icon="Pin"/>                
             </StackPanel>     
             <StackPanel Grid.Column="1" x:Name="rightBottomAppBar" Orientation="Horizontal" HorizontalAlignment="Right">                                                     
                 <AppBarButton Label="Play" Icon="Play"/>       
                 <AppBarButton Label="Pause" Icon="Pause"/>       
                 <AppBarButton Label="Stop" Icon="Stop"/>         
                 <AppBarButton Label="Previous" Icon="Previous"/>       
                 <AppBarButton Label="Next" Icon="Next"/>        
             </StackPanel>   
          </Grid>   
       </AppBar>  
    </Page.BottomAppBar>

    那么对于Windows 10,在拉伸的过程中,中间部分的控件就会慢慢消失啦。以下这张图片呢,是我在拉伸到中间有2个控件刚好重叠的时候啦。至于把AppBarButton设计成这样是好是坏大家自己决定咯,我反正觉得这样不好呢。不过有意思的是,即便如此,它们彼此的Click事件还都是有效的噢,会区分左右两部分,而不会叠在一起。

    这里写图片描述

    当然啦,这个的应用远不是应用栏这么简单哟,对于其他的前景,比如有两个TextBlock在屏幕左右两侧,当应用把收缩变小之后也可以让这个TextBlock叠成2层在屏幕的一边。

    在应用栏上添加菜单

    我们都见过有菜单的应用栏按钮对吧,这个的实现其实也挺简单的。用Flyout属性就好了。

    <Page.BottomAppBar>        
        <CommandBar> 
            <AppBarButton Icon="Rotate" Label="Rotate">                
                <AppBarButton.Flyout>                    
                    <MenuFlyout>   
                       <MenuFlyoutItem Text="Rotate 90" Click="MenuFlyoutItem_Click" Tag="Rotate90"/>           
                       <MenuFlyoutItem Text="Rotate 180" Click="MenuFlyoutItem_Click" Tag="Rotate180"/>      
                       <MenuFlyoutItem Text="Rotate 270" Click="MenuFlyoutItem_Click" Tag="Rotate270"/>                    
                   </MenuFlyout>                
               </AppBarButton.Flyout>            
           </AppBarButton>     
       </CommandBar>   
    </Page.BottomAppBar>

    Tag属性,就相当于做一个标签。下面这段代码就让Flyout菜单发挥作用了。

    private void MenuFlyoutItem_Click(object sender, RoutedEventArgs e)
    {
        MenuFlyoutItem selectedItem = sender as MenuFlyoutItem;
    
        if (selectedItem != null)
        {
            if (selectedItem.Tag.ToString() == "Rotate90")
            {
                DoRotate(90);
            }
            else if (selectedItem.Tag.ToString() == "Rotate180")
            {
                DoRotate(180);
            }
            else if (selectedItem.Tag.ToString() == "Rotate270")
            {
                DoRotate(270);
            }
        }
    }
    

    版权声明:本文为 NoMasp柯于旺 原创文章,如需转载请联系本人。

  • 相关阅读:
    升级windows 11小工具
    windows 10更新升级方法
    您需要了解的有关 Oracle 数据库修补的所有信息
    Step by Step Apply Rolling PSU Patch In Oracle Database 12c RAC Environment
    Upgrade Oracle Database Manually from 12.2.0.1 to 19c
    如何应用版本更新 12.2.0.1.210420(补丁 32507738 – 2021 年 4 月 RU)
    xtrabackup 安装、备份和恢复
    Centos_Lvm expand capacity without restarting CentOS
    Centos_Lvm_Create pv vg lv and mount
    通过全备+relaylog同步恢复被drop的库或表
  • 原文地址:https://www.cnblogs.com/NoMasp/p/4785984.html
Copyright © 2011-2022 走看看