哦把橄欖石帶偶。。。。。先聲明下下,接下來將要寫的一些關於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
歡迎與鳥叔一起探討學習,共同成長,鳥叔的微博 多了特