WPF:蒙版弹出窗体

时间:2024-03-01 07:59:20

一般设计

<Grid>
    <Grid x:Name="gridMain">
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Button Grid.Column="0" x:Name="btnWindow1" Width="50" Height="40" Content="子窗体1" Click="btnOpen_Click"></Button>
        <Button Grid.Column="1" x:Name="btnWindow2" Width="50" Height="40" Content="子窗体2" Click="btnOpen2_Click"></Button>
    </Grid>
    <Grid x:Name="gridChidWindow" Visibility="Hidden">
        <Grid Background="DarkGray" Opacity="0.8"></Grid>
        <Grid x:Name="gridChidWindowContent" Margin="40,80,40,40">
            <Border BorderBrush="Red" BorderThickness="2"></Border>
        </Grid>
        <Button x:Name="btnChidWindowClose" Content="CLose" Width="40" Height="40" Margin="0,60,20,20" Background="LightGray" HorizontalAlignment="Right" VerticalAlignment="Top" Click="btnChidWindowClose_Click"></Button>
    </Grid>
    <Grid x:Name="gridChidWindow2" Visibility="Hidden">
        <Grid Background="DarkGray" Opacity="0.8"></Grid>
        <Grid x:Name="gridChidWindowContent2" Margin="40,80,40,40">
            <Border BorderBrush="Blue" BorderThickness="2"></Border>
        </Grid>
        <Button x:Name="btnChidWindowClose2" Content="CLose" Width="40" Height="40" Margin="0,60,20,20" Background="LightGray" HorizontalAlignment="Right" VerticalAlignment="Top" Click="btnChidWindowClose2_Click"></Button>
    </Grid>
</Grid>
private void btnChidWindowOpen_Click(object sender, RoutedEventArgs e)
{
    gridChidWindow.Visibility = Visibility.Visible;
}
private void btnChidWindowClose_Click(object sender, RoutedEventArgs e)
{
    gridChidWindow.Visibility = Visibility.Hidden;
}


封装成用户控件


xmlns:ws="https://wesson.com/WessonControl"
<Grid Name="gridContentBackground" VerticalAlignment="Stretch">
    <Grid Background="DarkGray" Opacity="0.8"></Grid>
    <Grid Name="gridContent" Margin="{Binding FormMargin, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"></Grid>

    <Grid HorizontalAlignment="Right" VerticalAlignment="Top" ButtonBase.Click="Grid_Click">
       <Border x:Name="brdClose" Width="25" Height="25" Margin="10" Background="Black" ws:BorderElement.Circular="True"/>
       <Button x:Name="btnClose" HorizontalAlignment="Right" VerticalAlignment="Top" Width="25" Height="25"  Margin="10"  Padding="0"
           Background="Transparent" Foreground="LightGray" Style="{StaticResource ButtonIcon}" ws:IconElement.Geometry="{StaticResource ClosePopGeometry}"
           Content="Close子窗口" ToolTip="关闭" Click="BtnContentClose_Click"  />
    </Grid> 
</Grid>
using System;
using System.Windows;
using System.Windows.Controls;
/// <summary>
/// 蒙版弹出窗体
/// </summary>
public partial class UC_ChildForm : UserControl
{
    private readonly static Thickness _defaultThickness = new Thickness(20);
    private readonly static Type _classType = typeof(UC_ChildForm);

    /// <summary>
    /// 弹出窗体相对边距
    /// </summary>
    public Thickness FormMargin
    {
        get { return (Thickness)GetValue(FormMarginProperty); }
        set { SetValue(FormMarginProperty, value); }
    }
    public static readonly DependencyProperty FormMarginProperty =
        DependencyProperty.Register("FormMargin", typeof(Thickness), _classType, new PropertyMetadata(_defaultThickness, OnFormMarginChanged));
    private static void OnFormMarginChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ctl = (UC_ChildForm)d;
        ctl.OnFormMarginChanged((Thickness)e.NewValue);
    }
    private void OnFormMarginChanged(Thickness newValue)
    {
        brdClose.Margin = new Thickness(10, newValue.Top - 10, newValue.Right - 10, 10);
        btnClose.Margin = new Thickness(10, newValue.Top - 10, newValue.Right - 10, 10);
    }

    /// <summary>
    /// 弹出窗体的宽
    /// </summary>
    public double FormWidth
    {
        get { return (double)GetValue(FormWidthProperty); }
        set { SetValue(FormWidthProperty, value); }
    }
    public static readonly DependencyProperty FormWidthProperty =
        DependencyProperty.Register("FormWidth", typeof(double), _classType, new PropertyMetadata(0.0, OnFormWidthChanged));
    private static void OnFormWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ctl = (UC_ChildForm)d;
        ctl.OnFormWidthChanged((double)e.NewValue);
    }
    private void OnFormWidthChanged(double width)
    {
        if (gridContent.Children.Count == 0) return;
        // 解决关闭按钮不随父窗口大小变化问题
        var old = FormMargin;
        var marginHori = (this.ActualWidth - width) / 2;
        old.Left = marginHori;
        old.Right = marginHori;
        FormMargin = old;
    }

    /// <summary>
    /// 弹出窗体的高
    /// </summary>
    public double FormHeight
    {
        get { return (double)GetValue(FormHeightProperty); }
        set { SetValue(FormHeightProperty, value); }
    }
    public static readonly DependencyProperty FormHeightProperty =
        DependencyProperty.Register("FormHeight", typeof(double), _classType, new PropertyMetadata(0.0, OnFormHeightChanged));
    private static void OnFormHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ctl = (UC_ChildForm)d;
        ctl.OnFormHeightChanged((double)e.NewValue);
    }
    private void OnFormHeightChanged(double height)
    {
        if (gridContent.Children.Count == 0) return;
        // 解决关闭按钮不随父窗口大小变化问题
        var old = FormMargin;
        var marginVeri = (this.ActualHeight - height) / 2;
        old.Top = marginVeri;
        old.Bottom = marginVeri;
        FormMargin = old;
    }

    /// <summary>
    /// 声明路由事件
    /// 参数:要注册的路由事件名称,路由事件的路由策略,事件处理程序的委托类型(可自定义),路由事件的所有者类型
    /// </summary>
    public static readonly RoutedEvent FormClosedEvent = EventManager.RegisterRoutedEvent("FormClosed", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UC_ChildForm));
    /// <summary>
    /// 窗体关闭的路由事件
    /// </summary>
    public event RoutedEventHandler FormClosed
    {
        // 将路由事件添加路由事件处理程序
        add { AddHandler(FormClosedEvent, value); }
        // 从路由事件处理程序中移除路由事件
        remove { RemoveHandler(FormClosedEvent, value); }
    }
    public static readonly RoutedEvent FormClosingEvent = EventManager.RegisterRoutedEvent("FormClosing", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UC_ChildForm));
    /// <summary>
    /// 窗体正在关闭时的路由事件
    /// </summary>
    public event RoutedEventHandler FormClosing
    {
        add { AddHandler(FormClosingEvent, value); }
        remove { RemoveHandler(FormClosingEvent, value); }
    }

    public UC_ChildForm()
    {
        InitializeComponent();
        Visibility = Visibility.Hidden;
    }

    private void BtnContentClose_Click(object sender, RoutedEventArgs e)
    {
        e.RoutedEvent = FormClosingEvent;
        this.RaiseEvent(e);
    }
    private void Grid_Click(object sender, RoutedEventArgs e)
    {
        var ui = gridContent.Children[0];
        var value = InvokeGetProperty(ui, "FormData");
        FormCloseMethod(value);

        Hide();
        e.Handled = true;
    }
    /// <summary>
    /// 动态获取对象的属性值
    /// </summary>
    /// <param name="obj">指定的对象</param>
    /// <param name="propertyName">属性名称(字符串形式)</param>
    /// <param name="args">传递给属性用的参数</param>
    /// <returns></returns>
    private object InvokeGetProperty(object obj, string propertyName)
    {
        Type type = obj.GetType();
        var prop = type.GetProperty(propertyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
        if (null != prop && prop.CanRead)
        {
            return prop.GetValue(obj, null);
        }
        return null;
    }
    private void FormCloseMethod(object value)
    {
        // 定义传递参数
        var args = new RoutedPropertyChangedEventArgs<object>(default, value, FormClosedEvent);
        // 引用自定义路由事件
        this.RaiseEvent(args);
    }

    public void Show(UIElement uIElement)
    {
        this.Visibility = Visibility.Visible;
        gridContentBackground.Visibility = Visibility.Visible;
        gridContent.Children.Clear();
        gridContent.Children.Add(uIElement);
    }
    public void Hide()
    {
        this.Visibility = Visibility.Hidden;
        gridContentBackground.Visibility = Visibility.Hidden;
        gridContent.Children.Clear();
        FormMargin = _defaultThickness;
        FormWidth = 0;
        FormHeight = 0;
    }

}

<Grid>
    <Grid>
        <!--主窗口-->
    </Grid> 
    <local:UC_ChildForm x:Name="ucChildDlg" FormClosed="UcChildDlg_FormClosed" FormClosing="UcChildDlg_FormClosing"/>
</Grid>
UC_UserControl2 ucInfo;
private void BtnDetails_Click(object sender, RoutedEventArgs e)
{
    ucInfo = new UC_UserControl2();
    ucChildDlg.Show(ucInfo);
    ucChildDlg.FormMargin = new Thickness(20,30,40,50);
    // ucChildDlg.FormWidth = 600;
    // ucChildDlg.FormHeight = 400;
}
private void UcChildDlg_FormClosing(object sender, RoutedEventArgs e)
{
    //  e.Handled = true;
}
private void UcChildDlg_FormClosed(object sender, RoutedEventArgs e)
{
    var args = (RoutedPropertyChangedEventArgs<object>)e;
    lbMsg.Text = args.NewValue?.ToString();
}