鳥叔學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

 

歡迎與鳥叔一起探討學習,共同成長,鳥叔的微博 多了特

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM