防止用户控件关闭 WPF C#

Prevent a user control from closing WPF C#

我有一个用户填写表单的应用程序,如果用户不按保存并加载另一个表单control/button,我需要阻止用户离开并销毁用户控件。用户控件上没有关闭事件。我试过 Unloaded 但这已经与可视化树断开连接。 我是否必须在整个过程中创建变量才能检查? 有针对这种情况的活动吗?

更新

所以我有一个 window 用于应用程序,许多用户控件在网格中加载,例如,如果客户端按下联系人,那么新的联系人用户控件将作为 [=19= 的子项出现].如果用户没有按下保存,我希望用户控件不会被删除并提示一条消息。希望解释得更多一些。

您可以覆盖 OnClosing 事件。

    protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
    {
        base.OnClosing(e);
    }

因此,据我了解您的问题,您在 window 的主要代码中交换了用户控件。如果输入不完整,您不希望交换其中一个控件。

你必须自己编写代码。可能您在主 window 的代码中有一个类似下面的方法来切换到另一个 UserControl:

private void SwapView(UserControl newView)
{
    // Remove old user control
    ...

    // Show new user control
    ...
}

您需要的是 UserControl 派生的 class 中的一些标志,指示是否可以交换。最好,你定义一个这样的接口:

public interface IView
{
    bool CanClose();
}

并让所有 UserControl实施它:

public class MyControl : UserControl, IView
{
    ...

    public bool CanClose()
    {
        // Determine whether control can be closed
        bool result = ...
        return result;
    }

    ...
}

那你可以把上面的方法改成:

private void SwapView(IView newView)
{
    // Get current view
    IView currentView = ...

    // Check whether it can be closed
    if (!currentView.CanClose())
    {
        ...
        return;
    }

    // Remove old user control
    ...

    // Show new user control
    ...
}

您可以轻松扩展它,以便向用户显示一条消息,提供无法更改视图的原因。

最简单也可能是最优雅的解决方案是使用这个附件 属性

public static class WindowEventHelpers
    {
        #region Static Fields

        /// <summary>
        /// Attached property to define the command to run when the windows is closing
        /// </summary>
        public static readonly DependencyProperty WindowClosingCommandProperty = DependencyProperty.RegisterAttached(
            "WindowClosingCommand",
            typeof(ICommand),
            typeof(WindowEventHelpers),
            new PropertyMetadata(null, OnWindowClosingCommandChanged));


        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// Returns the WindowClosingCommand dependency property value.
        /// </summary>
        /// <param name="target">
        /// The <see cref="DependencyProperty"/> identifier.
        /// </param>
        /// <returns>
        /// The WindowClosingCommand dependency property value.
        /// </returns>
        public static ICommand GetWindowClosingCommand(DependencyObject target)
        {
            return (ICommand)target.GetValue(WindowClosingCommandProperty);
        }

        /// <summary>
        /// Set the WindowClosingCommand dependency property value
        /// </summary>
        /// <param name="target">
        /// The <see cref="DependencyProperty"/> identifier.
        /// </param>
        /// <param name="value">
        /// The dependency property value.
        /// </param>
        public static void SetWindowClosingCommand(DependencyObject target, ICommand value)
        {
            target.SetValue(WindowClosingCommandProperty, value);
        }

        /// <summary>
        /// Returns the WindowClosingCommand dependency property value.
        /// </summary>
        /// <param name="target">
        /// The <see cref="DependencyProperty"/> identifier.
        /// </param>
        /// <returns>
        /// The WindowClosingCommand dependency property value.
        /// </returns>
        public static ICommand GetWindowContentRenderedCommand(DependencyObject target)
        {
            return (ICommand)target.GetValue(WindowContentRenderedCommandProperty);
        }

        #endregion

        #region Methods

        private static void ClosingEventHandler(object sender, CancelEventArgs e)
        {
            var control = (Window)sender;
            var command = (ICommand)control.GetValue(WindowClosingCommandProperty);
            command.Execute(e);
        }


        private static void OnWindowClosingCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            var command = (ICommand)e.NewValue;

            if (target is Window)
            {
                // var fe = (FrameworkElement)target;
                var control = (Window)target;

                //check if we need to add the event handler or we need to remove it
                if ((command != null) && (e.OldValue == null))
                {
                    control.Closing += ClosingEventHandler;
                }
                else if ((command == null) && (e.OldValue != null))
                {
                    control.Closing += ClosingEventHandler;
                }
            }
        }


        #endregion
    }

在XAML中你需要绑定

ap:WindowEventHelpers.WindowClosingCommand="{绑定 CheckBeforeClosing}"

最后在代码隐藏或 ViewModel 中您需要定义并启动一个新命令:

public ICommand CheckBeforeClosing
{
  get;
  private set;
}

this.CheckBeforeClosing = new Command<CancelEventArgs>(this.CheckBeforeClosingMethod);

private void CheckBeforeClosingMethod(CancelEventArgs EventArgs)
{
      //Cancel the closing TODO Add the check
      EventArgs.Cancel = true;       
}