[WPF][Silverlight] 自己做Modal元件

有使用過Silverlight/WPF的朋友們不知道有沒有遇過一個問題:有時候想要跳出一個元件跟使用者互動,而且要鎖住原來的主畫面,等使用者操作完才能繼續操作主畫面,可是用MessageBox的話功能不夠,用ChildWindow的話功能又太多或是太複雜之類的問題…

有使用過Silverlight/WPF的朋友們不知道有沒有遇過一個問題:有時候想要跳出一個元件跟使用者互動,而且要鎖住原來的主畫面,等使用者操作完才能繼續操作主畫面,可是用MessageBox的話功能不夠,用ChildWindow的話功能又太多或是太複雜之類的問題…

難道就不能自訂一個元件,當它顯示的時候,會自動讓主畫面被鎖住,而且該元件的外觀和操作方式都可以自訂嗎?其實只要善用Grid容器,就可以簡單的做到這個功能喔!!

方法如下:

 

1. 首先我們打開一個標準的Silverlight+Web專案(WPF也可以喔),接著增加一個UserControl(範例中取名為MyModalControl)。

接著修改MyModalControl.xaml的內容,將控制項本身LayoutRoot這個Grid的寬和高都設為Auto

image

 

2. 修改LayoutRoot背景色為#4C4969CC(透明度為30%)

image

 

3. 放置要和使用者互動的元件,為了精簡教學過程,怎麼做的這邊就不詳述,完成後如下圖。

image

 

4. 加入按鈕的Click事件,並加入移除這個控制項的程式碼,完成後的xaml與cs檔如下:

MyModalControl.xaml
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    mc:Ignorable="d"
    x:Class="FakeModal.MyModalControl"
    d:DesignWidth="640" d:DesignHeight="480">
 
    <Grid x:Name="LayoutRoot" Background="#4C4969CC">
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <StackPanel.Effect>
                <DropShadowEffect Opacity="0.5"/>
            </StackPanel.Effect>
            <i:Interaction.Behaviors>
                <ei:MouseDragElementBehavior ConstrainToParentBounds="True"/>
            </i:Interaction.Behaviors>
            <Border BorderBrush="Black" BorderThickness="2,2,2,0" Height="32" Width="200" CornerRadius="10,10,0,0" Margin="10,0,0,0" HorizontalAlignment="Left" Background="White">
                <TextBlock TextWrapping="Wrap" Text="FakeModal" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18.667"/>
            </Border>
            <Border BorderBrush="Black" BorderThickness="2" Width="400" Height="150" CornerRadius="10" Background="White">
                <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                    <TextBlock TextWrapping="Wrap" Text="Is to make a fake modal that simple?" FontSize="18.667" Margin="0"/>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,30,0,0">
                        <Button x:Name="btnYes" Content="Yes" Width="80" Height="32" FontSize="16" Margin="10,0" Click="btnYes_Click"/>
                        <Button x:Name="btnNo" Content="No" Width="80" Height="32" FontSize="16" Margin="10,0" Click="btnNo_Click"/>
                    </StackPanel>
                </StackPanel>
            </Border>
        </StackPanel>
    </Grid>
</UserControl>

 

MyModalControl.cs
using System.Windows.Controls;
 
namespace FakeModal
{
    public partial class MyModalControl : UserControl
    {
        public MyModalControl()
        {
            InitializeComponent();
        }
 
        private void btnYes_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            //you can do something here.
            (this.Parent as Panel).Children.Remove(this);
        }
 
        private void btnNo_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            //you can do something here.
            (this.Parent as Panel).Children.Remove(this);
        }
    }
}

 

5. 到這邊就算是完成啦,再來就是讓它上場表演的時候了,在MainPage.xaml放一個Button叫它出來吧!!

image

 

MainPage.xaml
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="FakeModal.MainPage"
    Width="Auto" Height="Auto">
 
    <Grid x:Name="LayoutRoot" Background="White">
        <Button x:Name="btnShowModal" Content="Show Fake Modal" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18.667" Click="btnShowModal_Click"/>
    </Grid>
</UserControl>

 

MainPage.cs
using System.Windows.Controls;
 
namespace FakeModal
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }
 
        private void btnShowModal_Click(object sender, System.Windows.RoutedEventArgs e)
        {            
            this.LayoutRoot.Children.Add( new MyModalControl());
        }
    }
}

 

6. 執行結果如下:

專案下載: