打开/关闭窗户时我做错什么了吗?

时间:2018-12-07 13:25:07

标签: c# wpf window

我注意到我在应用程序中打开的窗口中出现了令人不安的行为:关闭窗口本身很长时间后,命令和(最引人注目的是)它们的“可以执行”方法才被触发。

这是我倾向于做事的简化示例:

public class AllMaxThemedWindow : DevExpress.Xpf.Core.ThemedWindow, INotifyPropertyChanged
{
    public static DependencyProperty ShowMinimizeButtonProperty = DependencyProperty.Register("ShowMinimizeButton", typeof(Boolean), typeof(AllMaxThemedWindow), new PropertyMetadata(true));
    public Boolean ShowMinimizeButton
    {
        get => (Boolean)GetValue(ShowMinimizeButtonProperty);
        set => SetValue(ShowMinimizeButtonProperty, value);
    }
    //Maximize and Close DPs as well

    public AllMaxThemedWindow()
    {
        Loaded += AllMaxThemedWindow_Loaded;
    }

    private void AllMaxThemedWindow_Loaded(Object sender, RoutedEventArgs e)
    {
        if (!ShowMinimizeButton)
        {
            var button = (Button)DevExpress.Xpf.Core.Native.LayoutHelper.FindElementByName(this, DXWindow.ButtonParts.PART_Minimize.ToString());
            button.Visibility = Visibility.Collapsed;
        }

        //Maximize and Close checks as well

        //If neither maximize nor minimize is allowed, then prevent the system menu from being shown (via button or right-click).
        if (!ShowMaximizeButton && !ShowMinimizeButton)
        {
            var hwnd = new WindowInteropHelper(this).Handle;
            NativeMethods.SetWindowLong(hwnd, GWL_STYLE, NativeMethods.GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
        }
    }
}

<atw:AllMaxThemedWindow x:Class="Antero.Windows.ThemedWindowInstance">
    <atw:AllMaxThemedWindow.DataContext>
        <vm:ThemedWindowInstanceViewModel />
    </atw:AllMaxThemedWindow.DataContext>
</atw:AllMaxThemedWindow>

//...opened this way in a view model's button command handler
new ThemedWindowInstance().ShowDialog(true);

除此之外,没有什么特别的事情发生。最终,它只是一个Window,并且该窗口已作为模式打开。然后,用户单击X将其关闭。

那是坏事发生的时候。例如,在一个窗口上有一个Save按钮,该按钮绑定到具有“可以执行”方法的命令(在其视图模型中)。在关闭窗口很长时间之后,该方法将继续被触发。实际上,它似乎永远会触发。

我来自WinForms领域,所以我习惯做Dispose之类的事情,但是在WPF中我似乎无法使用。那么,在WPF世界中,到底是什么让窗口(或其视图模型)永远悬而未决?

1 个答案:

答案 0 :(得分:-1)

您的ICommand实现应实现CanExecuteChanged事件。而且,您应该在每次执行条件实际更改时触发此事件。通常,ICommand实现具有NotifyCanExecuteChanged方法。

public class DelegateCommand : ICommand
{
    private readonly Action<object> _execute = null;
    private readonly Predicate<object> _canExecute = null;

    #region Constructors

    public DelegateCommand(Action<object> execute)
        : this(execute, null) { }

    public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion

    #region ICommand Members

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return _canExecute != null ? _canExecute(parameter) : true;
    }

    public void Execute(object parameter)
    {
        if (_execute != null)
            _execute(parameter);
    }

    public void NotifyCanExecuteChanged()
    {
        if(CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }

    #endregion

}