简体   繁体   English

阻止用户控件关闭WPF C#

[英]Prevent a user control from closing WPF C#

I have an application in which a user fills out a form, if the user doesn't press save and loads another control/button i need to stop the user leaving and destroying the user control. 我有一个用户填写表单的应用程序,如果用户没有按下保存并加载另一个控件/按钮我需要停止用户离开并销毁用户控件。 There isn't a Closing event on a User Control. 用户控件上没有Closing事件。 i tried Unloaded but this has already disconnected from the visual tree. 我尝试过卸载,但这已经与可视树断开了。 Do i have to have to create variables throughout to check? 我是否必须在整个过程中创建变量才能检查? is there an event to use for this situation? 是否有用于此情况的事件?

Update 更新

So i have one window for the application and many user controls load in a grid, for example if a client press contact then a new contact user control will occur as a child of the window. 所以我有一个应用程序窗口和许多用户控件在网格中加载,例如,如果客户端按下联系人,则新的联系人用户控件将作为窗口的子项发生。 If the user hasn't pressed save i want the user control to not be removed and prompt a message. 如果用户没有按下保存,我希望不删除用户控件并提示消息。 Hope that explains a bit more. 希望能解释一下。

So, as far as I understand your question, you swap user controls in your main window's code. 所以,据我所知,你可以在主窗口的代码中交换用户控件。 You don't want one of the controls to be swapped if inputs are incomplete. 如果输入不完整,您不希望交换其中一个控件。

You have to code this yourself. 你必须自己编写代码。 Probably you have a method like the following in your main window's code to switch to another UserControl : 可能你在主窗口的代码中有一个类似下面的方法来切换到另一个UserControl

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

    // Show new user control
    ...
}

What you need is some flag in your UserControl derived class that indicates whether it is possible to swap or not. 你需要的是你的UserControl派生类中的一些标志,指示是否可以交换。 Best, you define an interface like this: 最好,你定义这样的界面:

public interface IView
{
    bool CanClose();
}

and have all your UserControl s implement it: 并让所有 UserControl实现它:

public class MyControl : UserControl, IView
{
    ...

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

    ...
}

Then you can change the above method to: 然后您可以将上述方法更改为:

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
    ...
}

You can easily extend this so that a message is shown to the user providing a reason for not being able to change views. 您可以轻松扩展它,以便向用户显示消息,从而提供无法更改视图的原因。

The simpliest and probably most elegant solution is to use this attached property 最简单且可能最优雅的解决方案是使用此附加属性

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
    }

In the XAML you then need to bind 在XAML中,您需要绑定

ap:WindowEventHelpers.WindowClosingCommand="{Binding CheckBeforeClosing}" ap:WindowEventHelpers.WindowClosingCommand =“{Binding CheckBeforeClosing}”

finally in the code behind or ViewModel you need to define and initiate a new command: 最后在后面的代码或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;       
}

You can override the OnClosing event. 您可以覆盖OnClosing事件。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM