在WPF的頁面中我們肯定會遇到這樣的需求:彈出一個對話框讓用戶進行一些選擇和輸入,當用戶在該對話框上的操作結束並關閉對話框后再返回到主頁面進行其他操作。這其實就是一個很典型的模態對話框的應用。在WPF的Window中我們可以創建一個Window並調用它的ShowDialog()方法來滿足上面的需求。可是這樣的方法在WPF頁面上卻行不通。原因是:用ShowDialog()方法彈出的對話框跟瀏覽器是相互獨立的。由於彈出的對話框跟瀏覽器分別在兩個不同的窗口中,所以並不能達到模態對話框的需求。
下面給大家介紹一種用Popup來模擬模態對話框的方法。彈出的對話框是覆蓋在WPF頁面的上面。用戶只有在關閉了對話框之后才能返回原來的頁面。
比如現在有下面一個簡單的WPF頁面。

該頁面的xaml文件也很簡單:
- <Page x:Class="WpfModalDialog.MainPage"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="MainPage">
- <StackPanel x:Name="MainPanel">
- <Grid>
- <Button Height="28" Margin="0,30,0,0" Name="BtnShowDlg" VerticalAlignment="Top" HorizontalAlignment="Center">Show Modal Dialog</Button>
- <Label Height="28" Margin="0,68,0,0" Width="360" Name="labelString" VerticalAlignment="Top" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" BorderThickness="1" BorderBrush="DarkBlue">Click the above button</Label>
- </Grid>
- </StackPanel>
- </Page>
現在要實現這樣的功能:點擊按鈕彈出一個模態對話框讓用戶輸入一個字符串,然后在頁面的文本框里面顯示剛才用戶輸入的字符串。
下面是具體的截圖:


為了實現上面的功能,首先在xaml文件里面加上一個Popup:
- <Popup Name="ModalDialog" StaysOpen="True" Placement="Center">
- <Border BorderThickness="2" BorderBrush="SteelBlue" Width="400" Height="130">
- <Grid Background="White">
- <DockPanel Height="28" VerticalAlignment="Top" Background="SteelBlue">
- <TextBox Height="26" Name="TxtBoxTitle" Width="120" Background="SteelBlue" BorderThickness="0" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="White" FontSize="16" Focusable="False" IsHitTestVisible="False" IsTabStop="False" VerticalContentAlignment="Center">WPF Modal Dialog</TextBox>
- <Button Height="26" Name="BtnClose" Width="26" HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="16" Background="SteelBlue" Click="Dlg_BtnClose_Click">X</Button>
- </DockPanel>
- <Grid Margin="0,30,0,0">
- <Label Margin="15,0,0,0" Height="28" VerticalAlignment="Top" HorizontalAlignment="Left" VerticalContentAlignment="Center" >Input a string: </Label>
- <TextBox Height="28" Name="TxtBoxInput" Width="360" HorizontalAlignment="Center" VerticalContentAlignment="Center"/>
- <Button Margin="0,60,100,0" Height="22" Width="68" HorizontalAlignment="Right" Click="Dlg_BtnOK_Click">OK</Button>
- <Button Margin="0,60,15,0" Height="22" Width="68" HorizontalAlignment="Right" Click="Dlg_BtnClose_Click">Cancel</Button>
- </Grid>
- </Grid>
- </Border>
- </Popup>
在Popup里面的布局跟普通的WPF的Window和Page用的是一樣的方法。你就把Popup當成一個容器就行了。然后給BtnShowDlog加上一個Click事件。完整的xaml代碼是下面這樣的:
- <Page x:Class="WpfModalDialog.MainPage"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="MainPage">
- <StackPanel x:Name="MainPanel">
- <Grid>
- <Button Height="28" Margin="0,30,0,0" Name="BtnShowDlg" VerticalAlignment="Top" HorizontalAlignment="Center" Click="BtnShowDlg_Click">Show Modal Dialog</Button>
- <Label Height="28" Margin="0,68,0,0" Width="360" Name="labelString" VerticalAlignment="Top" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" BorderThickness="1" BorderBrush="DarkBlue">Click the above button</Label>
- </Grid>
- <Popup Name="ModalDialog" StaysOpen="True" Placement="Center">
- <Border BorderThickness="2" BorderBrush="SteelBlue" Width="400" Height="130">
- <Grid Background="White">
- <DockPanel Height="28" VerticalAlignment="Top" Background="SteelBlue">
- <TextBox Height="26" Name="TxtBoxTitle" Width="120" Background="SteelBlue" BorderThickness="0" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="White" FontSize="16" Focusable="False" IsHitTestVisible="False" IsTabStop="False" VerticalContentAlignment="Center">WPF Modal Dialog</TextBox>
- <Button Height="26" Name="BtnClose" Width="26" HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="16" Background="SteelBlue" Click="Dlg_BtnClose_Click">X</Button>
- </DockPanel>
- <Grid Margin="0,30,0,0">
- <Label Margin="15,0,0,0" Height="28" VerticalAlignment="Top" HorizontalAlignment="Left" VerticalContentAlignment="Center" >Input a string: </Label>
- <TextBox Height="28" Name="TxtBoxInput" Width="360" HorizontalAlignment="Center" VerticalContentAlignment="Center"/>
- <Button Margin="0,60,100,0" Height="22" Width="68" HorizontalAlignment="Right" Click="Dlg_BtnOK_Click">OK</Button>
- <Button Margin="0,60,15,0" Height="22" Width="68" HorizontalAlignment="Right" Click="Dlg_BtnClose_Click">Cancel</Button>
- </Grid>
- </Grid>
- </Border>
- </Popup>
- </StackPanel>
- </Page>
最后,就是在cs文件里面添加代碼:
1. 添加一個顯示和關閉對話框的方法
- private void ShowModalDialog(bool bShow)
- {
- this.ModalDialog.IsOpen = bShow;
- this.MainPanel.IsEnabled = !bShow;
- }
代碼非常簡單,就是顯示對話框的時候使原來的頁面不可用;關閉對話框的時候使原來的網頁恢復為可用狀態。
2. 為主頁面上的“Show Modal Dialog”按鈕添加Click事件
- private void BtnShowDlg_Click(object sender, RoutedEventArgs e)
- {
- ShowModalDialog(true);
- }
調用ShowModalDialog方法來顯示對話框
3. 為對話框的Cancel按鈕和Close按鈕添加Click事件
- private void Dlg_BtnClose_Click(object sender, RoutedEventArgs e)
- {
- ShowModalDialog(false);
- }
調用ShowModalDialog方法使對話框不可見。
4. 為對話框的OK按鈕添加Click事件
- private void Dlg_BtnOK_Click(object sender, RoutedEventArgs e)
- {
- ShowModalDialog(false);
- labelString.Content = "The string is: " + TxtBoxInput.Text;
- }
首先使對話框不可見,然后修改根據用戶在對話框上的輸入來修改主頁面上的Label的文本內容。
通過上面的方法,就可以讓對話框跟主頁面顯示在同一個瀏覽器里,並且使用戶在關閉對話框之前不能做任何操作。也就是說,實現了一個模態對話框的所有機制。
PS:剛開始接觸WPF,通過搜索和學習,覺得這是用WPF實現模態對話框的一個好方法。也許還有更好的方法,我知道了之后會共享給大家。同時如果你知道更好的方法,希望你能告訴我。
