如何从用户控件里面关闭一个window?

How to close a window from the user control inside?

我有一个 WPF 程序,有时我打开一个 window:

    public object testCommand()
    {
        Window window = new Window
        {
            Title = "My User Control Dialog",
            Content = new OKMessageBox("Error Message"),
            SizeToContent = SizeToContent.WidthAndHeight,
            ResizeMode = ResizeMode.NoResize
        };
        window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
        window.ShowDialog();

        return null;
    }

用户控制XAML:

<UserControl x:Class="SolidX.Base.MessageBoxes.OKMessageBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:SolidX.Base.MessageBoxes"
             xmlns:viewProperties="clr-namespace:AppResources.Properties;assembly=AppResources"
             mc:Ignorable="d" 
             d:DesignHeight="150" d:DesignWidth="400">
    <Grid>
        <TextBlock x:Name="textMessage" Margin="10"/>
        <Grid Height="Auto" VerticalAlignment="Bottom">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <CheckBox Content="Don't show this again" HorizontalAlignment="Right" Margin="5,5,10,5"/>
            <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
                <Button x:Name="btnOk" Content="{x:Static viewProperties:Resources.Common_OK}" Height="25" VerticalAlignment="Center" Width="90" Margin="5"/>
            </StackPanel>
        </Grid>
    </Grid>
</UserControl>

用户控制代码隐藏:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SolidX.Base.MessageBoxes
{
    /// <summary>
    /// Interaction logic for OKMessageBox.xaml
    /// </summary>
    public partial class OKMessageBox : UserControl
    {
        public OKMessageBox(string Message)
        {
            InitializeComponent();
            textMessage.Text= Message;
        }
    }
}

并且在我的用户控件中,我尝试使用关闭 window 的按钮(目前,设置 Button.IsCancel = true; 有效,但我希望这是一个可重复使用的选项 - 本质上是我自己的this.Close;).

我在我的用户控件的代码隐藏中尝试了这个(正如其他几个 Whosebug 答案所建议的那样)但无济于事(parentWindow 始终为 null):

var parentWindow = Window.GetWindow(this);
parentWindow.Close();

如果您为您的 Window 使用 ViewModel class,您可以将 ViewModel class 设置为您的 Window 实例,并且 ViewModel 可以存储它的所有者.

例如 ViewModel:

public class CloseConfirmViewModel
{
    internal Window Owner { get; set; }

    public ICommand CloseCommand { get; private set; } // ICommand to bind it to a Button

    public CloseConfirmViewModel()
    {
        CloseCommand = new RelayCommand<object>(Close);
    }

    public void Close() // You can make it public in order to call it from codebehind
    {
        if (Owner == null)
            return;

        Owner.Close();
    }
}

为了使其正常工作,您必须将 ViewModel class 设置为您的 Window:

public partial class CloseConfirmWindow : Window
{
    public CloseConfirmWindow(CloseConfirmViewModel model)
    {
        DataContext = model;

        InitializeComponent();

        model.Owner = this;
    }
}

并且您正在以这种方式创建一个新实例:

var model = new CloseConfirmViewModel();
var closeWindow = new CloseConfirmWindow(model);
closeWindow.ShowDialog(); // Hopefully you've added a button which has the ICommand binded

您可以通过这种方式将 WindowCloseCommand 绑定到 UserControl 的按钮,或者如果您不使用命令,请调用 Close() 方法当点击 UC 的按钮时。

在用户控件中试试这个:

xaml

<UserControl .... Loaded="UserControl_Loaded">
    <!--  -->
</UserControl>

cs

public UserControl()
{
    InitializeComponent();
}

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    var window = Window.GetWindow(this);
    window.Close();
}

要关闭模式对话框,您应该设置 DialogResult: DialogResult = false;

None 这些方法对我有用。大多数只是关闭父 window。我使用的是主 window 中的 XAML 弹出窗口。有点像。

<DockPanel/>
   <Popup x:Name="puMyControl"/>
      <Local:UserControl />
   </Popup>
</DockPanel>

在我后面的主要 window 代码的其他地方,我添加了:

puMyControl.IsOpen = true;

我在 UserControl 中有一个取消按钮。 Popup 没有子项,因此我需要引用 Popup 的父项,即 DockPanel。

private void BtnClose_Click(object sender, RoutedEventArgs e)
{
    Popup pu = Parent as Popup;
    if ( pu != null )
    {
       DockPanel dp = pu.Parent as DockPanel;
       if (dp != null)
       {
          dp.Children.Remove(pu);
       }
    }
}

突然想到,我要删除的是 Popup,而不是 UserControl。 'this' 将引用 UserControl。正如您在上面看到的,我正在从 DockPanel 中删除 Popup。这导致了一个更简单、更通用的解决方案。

Popup pu = Parent as Popup;
if (pu != null)
{
   pu.IsOpen = false;
}