防止用户控件关闭 WPF C#

本文关键字:WPF 控件 用户 | 更新日期: 2023-09-27 17:55:41

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

更新

所以我有一个用于应用程序的窗口,并且许多用户控件在网格中加载,例如,如果客户端按联系人,那么一个新的联系人用户控件将作为窗口的子级出现。如果用户尚未按保存,我希望不会删除用户控件并提示一条消息。希望这能解释更多。

防止用户控件关闭 WPF C#

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

你必须自己编码。您可能在主窗口的代码中有一个类似以下内容的方法可以切换到另一个UserControl

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

您需要的是UserControl派生类中的某个标志,用于指示是否可以交换。 最好是定义如下接口:

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.WindowClosesingCommand="{Binding CheckBeforeClosesing}"

最后,在代码隐藏或 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;       
}

您可以重写 OnClosing 事件。

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