【问题标题】:Prevent a user control from closing WPF C#防止用户控件关闭 WPF C#
【发布时间】:2016-07-06 10:21:35
【问题描述】:

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

更新

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

【问题讨论】:

  • 我脑子里有一个变量作为标志,但它似乎太过时了。寻找基于事件的解决方案。
  • 也许 LostFocus 事件可能对您有所帮助。你能说得更具体点吗?
  • 所以,你需要阻止用户在不按特定按钮的情况下关闭子窗口,对吧?
  • 最好的方法可能是一个标志。如果尝试换页,用户控件没有保存,提示信息
  • 如果子窗口是用户控件,那是正确的:)

标签: c# wpf user-controls


【解决方案1】:

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

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

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

    // Show new user control
    ...
}

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

public interface IView
{
    bool CanClose();
}

并让你所有的UserControls 实施它:

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

您可以轻松扩展此功能,以便向用户显示一条消息,说明无法更改视图的原因。

【讨论】:

    【解决方案2】:

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

    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="{Binding 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;       
    }
    

    【讨论】:

      【解决方案3】:

      您可以覆盖 OnClosing 事件。

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

      【讨论】:

      • 感谢回复,用户控件没有 OnClosing 事件。
      猜你喜欢
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 2013-08-30
      • 1970-01-01
      • 2018-01-11
      • 1970-01-01
      • 1970-01-01
      • 2015-12-30
      相关资源
      最近更新 更多