鸟叔学Windows8开发(1):自定义弹出窗口

哦把橄榄石带偶。。。。。先声明下下,接下来将要写的一些关于Win8开发文章可能有些代码和网上一些博客的代码基本一致(哈哈大家一起借鉴学习,但是鸟叔表示在学习的过程中坚持原创),代码相像归相像,最重要的是要举一反三,刨根问底,弄清原理。要有鸟叔的思想。。。。。

 一、默认弹出框MessageDialog

   1、在学习自定义弹出窗口之前先学习下,WIN8自带的弹出窗口,直接上代码,然后分析下。

async protected void onOKClick(object sender, RoutedEventArgs e)
        {
            //第一步:先声明MessageDialog
            MessageDialog msgOne = new MessageDialog("弹出一个按钮");
            //第二步:给弹出框添加命令并添加处理方法
            msgOne.Commands.Add(new UICommand("确定", new UICommandInvokedHandler(OnUICommand)));
            //第三步:显示弹出框
            await msgOne.ShowAsync();
        }

大家可能注意到代码中出现了两个新的关键字:async和await,这是.NET4.5中为了处理异步操作更象同步操作代码而加入的,呵呵 好像有点没说清,具体大家可以去问MSDN。。。

  2、给弹出框添加多个命令和设置默认按钮命令索引

 //添加多个命令
            msgThree.Commands.Add(new UICommand("重试", new UICommandInvokedHandler(OnUICommand)));
            msgThree.Commands.Add(new UICommand("忽略", new UICommandInvokedHandler(OnUICommand)));
            msgThree.Commands.Add(new UICommand("取消", new UICommandInvokedHandler(OnUICommand)));
            //msgThree.Commands.Add(new UICommand("第四个命令", new UICommandInvokedHandler(OnUICommand)));
            //默认按钮索引
            msgThree.CancelCommandIndex = 2;//当用户按Esc键时触发这个命令
            msgThree.DefaultCommandIndex = 0;//当用户按ENTER键时促发这个命令

这么简单的代码鸟叔你也敢贴上来,呵呵大家知道为什么我把第四个命令注释掉了吗?因为鸟叔在添加超过三个命令的时候程序报异常了。这微软大哥也太坑了吧。。。所以说命令最多添加三个。
同时我们可以设置按ESC和ENTER键时关联的命令。

二、自定义弹出窗

这微软大哥自带的弹出窗也太那个啥了吧,不能自定义还只能添加最多三个按钮,这对于最近比较火的鸟叔来说完全不够用呀,我要做一个用户注册或者登录框怎么办,因为鸟叔爱学习,所以想到了自定义弹出框。

 原理:1、要和当前页面弹出一个和窗口大小一样的窗口(目的将下面的窗口不能使用),

          2、并且设置窗口透明度。

第一步:先创建一个模版控件:作为弹出窗的模版以后可以共用

然后VS自动给我们创建了一个Themes文件夹并且在下面创建了一个Generic.xaml(是一个资源字典文件)文件

在Generic.xaml文件中添加如下代码:

<Style  TargetType="local:PopupsControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:PopupsControl">
                    <Grid>
                        <!--下面两个控件占有一个空间,
                         如果Rectangle在前面,当不设置Rectangle的Canvas.ZIndex属性或者为0时ContentPresenter不会被遮盖
                         如果Rectangle在后面,当设置为0的时候也会被遮盖,因为默认为0这时候就认为后面加入的在前面加入的上面
                         这里我们没有设置Rectangle的With和height属性,他会自动继承,
                        但是一些不是继承属性的时候我们需要用TemplateBinding来绑定-->
                        <Rectangle Canvas.ZIndex="0" Fill="Black" Opacity="0.5"/>
                        <!--TemplateBinding在一些不能继承的属性中非常有用,为了能够让模版使用控件中的属性值-->
                        <!--ContentPresenter用于承载内容-->
                        <ContentPresenter Content="{TemplateBinding Content}"/>
                                            <!--HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                            ContentTemplate="{TemplateBinding ContentTemplate}"-->
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

 

 同时还有一个关联的后台代码文件(生成的名称和自己定义的一样)

添加如下后台代码

 public  class PopupsControl : ContentControl
    {
        //定义一个弹出框
        Popup pop = null;
        public PopupsControl()
        {
            this.DefaultStyleKey = typeof(PopupsControl);
            this.HorizontalContentAlignment = HorizontalAlignment.Stretch;
            this.Width = Window.Current.Bounds.Width;
            this.Height = Window.Current.Bounds.Height;
            pop = new Popup();
            this.pop.Child = this;//设置承载内容
        }
        //这段代码没弄懂,求讲解???
        public TransitionCollection PopTransitionCollection
        {
            get
            {
                if (pop.ChildTransitions == null)
                    pop.ChildTransitions = new TransitionCollection();
                return pop.ChildTransitions;
            }
        }
        //打开
        public virtual void OpenpPop()
        {
            if (pop != null)
                pop.IsOpen = true;
        }
        //关闭
        public virtual void ClosePop()
        {
            if (pop != null)
                pop.IsOpen = false;
        }
    }

第二步:添加一个用户控件:用于在弹出框中显示的内容,这里我们创建一个用户登录的界面。

 前台代码:

<UserControl
    x:Class="_2弹出框.MyUserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:_2弹出框"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="600">
    <UserControl.Resources>
        <Style x:Key="MyTextBlockStyle" TargetType="TextBlock">
            <Setter Property="FontSize" Value="20"/>
            <Setter Property="Margin" Value="5,10,0,5"/>
            <Setter Property="HorizontalAlignment" Value="Right"/>
        </Style>
        <Style x:Key="MyTextBoxStyle" TargetType="TextBox">
            <Setter Property="FontSize" Value="20"/>
            <Setter Property="Margin" Value="5,8,0,5"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
            <Setter Property="Width" Value="300"/>
        </Style>
        <!--当我们没有为style设置key的时候,页面中的所有被Style定义的目标类型都将使用,
        如果我们定义了Key,则要显示的引用才能使用-->
        <Style  x:Key="ss" TargetType="Button">
            <Setter Property="Foreground" Value="Red"/>
        </Style>
    </UserControl.Resources>
    
    <Grid  VerticalAlignment="Center" Background="Blue">
        <Grid Margin="0,60,0,30" Width="500">
            <StackPanel Orientation="Vertical">
                <TextBlock Text="登录" Margin="0,0,0,30" Style="{StaticResource PageHeaderTextStyle}"/>
                <Grid VerticalAlignment="Center">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="用户名:" Style="{StaticResource MyTextBlockStyle}" Grid.Column="0" Grid.Row="0"/>
                    <TextBox Style="{StaticResource  MyTextBoxStyle}" Grid.Column="1" Grid.Row="0"/>
                    <TextBlock Text="密  码:" Style="{StaticResource MyTextBlockStyle}" Grid.Column="0" Grid.Row="1"/>
                    <TextBox Style="{StaticResource MyTextBoxStyle}" Grid.Column="1" Grid.Row="1"/>
                    <Button Content="登录" FontSize="20" Grid.Column="1" Grid.Row="2" Width="80"  Height="45" Margin="230,0,0,0" Click="Button_Click_1"/>
                </Grid>
            </StackPanel>
        </Grid>
        </Grid>
</UserControl>

后台代码:

public sealed partial class MyUserControl1 : UserControl
    {
        PopupsControl pop = null;
        public MyUserControl1(PopupsControl p)
        {
            this.InitializeComponent();
            pop = p;
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            //关闭弹出框
            if (pop != null)
                pop.ClosePop();
        }
    }

第三步:显示我们的弹出窗口

  protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //1、实例化弹出窗
            PopupsControl pop = new PopupsControl();
            MyUserControl1 uc = new MyUserControl1(pop);
            //2、将自定义控件赋值给弹出窗
            pop.Content = uc;
            //3、显示
            pop.OpenpPop();
        }

效果:

接下来一同与鸟叔来学习下这个过程:

创建模版控件——〉创建用户控件并且赋值给模版空间——〉显示

在这个简单的过程中鸟叔又很多疑问????

1、在创建模版控件的时候我们在Generic.xaml中定义的style怎么关联到我们的控件上面的?

    在Generic.xaml和后台代码文件PopupsControl.cs中鸟叔发现并没有显示引用style的迹象。

例如我们在一个页面的Resources中定义的style需要我们定义Key(当我们定义key的时候我们必须在控件中显示引用才能有效果)或者不定义(这时候叫做类型样式,页面用的所有被样式作为目标的空间的样式都会改变,即使我们在控件中没有显示的引用)。大家跟着鸟叔看下上面的MyUserControl1.xaml中我的一段注释代码:

大家自己试试给style设置和不设置Key的效果,就会明白了。具体大家也可以多查下关于WPF/Silverlight样式方面的资料。

说了这么多好像没有回答我们的问题。因为我们需要显示样式中定义的效果的时候,我们需要显示应用或者使用类型样式。但是我们在定义模版控件的时候不管我们设不设置Key我们的模版控件都会引用该样式。

这时为什么呢 为什么呢,,,鸟叔最后发现当我们创建模版控件的时候VS会自动给我生成一个东东:

原来就是这个东西在作怪,鸟叔就是一个不淡定的人,鸟叔做了一件事情:帮文件夹名称或者文件名称改变的时候,发现我们的弹出框不能使用该样式了。鸟叔估计这个是VS在后台做了些关联的是但是不知道具体是怎么关联的,希望哪位知道的帮鸟叔讲解下。

2、弹出窗是怎么弹出来的(弹弹弹 弹走鱼尾纹。。。)

 a、鸟叔定义了一个Popup用来承载内容并且在当前窗口显示

 b、将一个继承于ContentControl的PopupsControl赋值给Popup实例,

 c、鸟叔在PopupsControl的控件模版的Style中定义了一个ControlTemplate并且设置了一个ContentPresenter(用来承载内容的)。

 d、然后将用户控件赋值给PopupsControl,最后其实是借助Popup弹出来的

 

总结:要真正理解弹出框我们需要学习,内容控件ContentControl、控件模版ControlTemplate,以及样式Style和资源Resource相关方面的知识。

 

博文参考:

http://blog.csdn.net/tcjiaan/article/details/7928040

http://blog.csdn.net/tcjiaan/article/details/8036375

 

欢迎与鸟叔一起探讨学习,共同成长,鸟叔的微博 多了特

 

 

 

 

posted on 2012-11-29 17:59  多了特  阅读(2819)  评论(1编辑  收藏  举报