ui 何时与命令分离? [英] When does the ui detach from commands?

查看:20
本文介绍了ui 何时与命令分离?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对这个真的很头疼.我有一个打开对话框的主窗口.对话框关闭后,对话框中绑定的命令的 CanExecute 方法仍在执行.这给我的应用程序造成了一些严重的问题.

I'm really scratching my head with this one. I have a mainwindow which opens a dialog. After the dialog closes, the CanExecute method on commands bound in the dialog are still executing. This is causing some serious problems in my application.

示例:

MainWindow 有一个带有点击处理程序的按钮.这是点击事件处理程序:

MainWindow has a button with a click handler. This is the click event handler:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        DialogWindow window = new DialogWindow();
        window.ShowDialog();
    }

在对话框中我将一个items控件绑定到了对话框窗口中的一个静态资源上,列表中的每个item都有一个命令:

In the dialog I bind an items control to a static resource in the dialog window, and each item in the list has a command:

<Window.Resources>

    <Collections:ArrayList x:Key="itemsSource">
        <local:ItemViewModel Description="A"></local:ItemViewModel>
        <local:ItemViewModel Description="B"></local:ItemViewModel>
        <local:ItemViewModel Description="C"></local:ItemViewModel>
    </Collections:ArrayList>

    <DataTemplate DataType="{x:Type local:ItemViewModel}">
            <Button Grid.Column="1" Command="{Binding Path=CommandClickMe}" Content="{Binding Path=Description}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
            </Button>
    </DataTemplate>

</Window.Resources>

<Grid>
    <ToolBar ItemsSource="{StaticResource itemsSource}"></ToolBar>
</Grid>

这是视图模型:

public class ItemViewModel
{
    private RelayWpfCommand<object> _commandClickMe;

    public RelayWpfCommand<object> CommandClickMe
    {
        get
        {
            if (_commandClickMe == null)
                _commandClickMe = new RelayWpfCommand<object>(obj => System.Console.Out.WriteLine("Hei mom"), obj => CanClickMe());

            return _commandClickMe;
        }
    }

    private bool CanClickMe()
    {
        return true;
    }

    public string Description { get; set; }

这是 DelegateCommand 的实现:

And this is the DelegateCommand implementation:

public class RelayWpfCommand<T> : ICommand
{
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    private readonly Predicate<T> _canExecute;
    private readonly Action<T> _execute;

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

    /// <summary>
    /// Forces a notification that the CanExecute state has changed
    /// </summary>
    public void RaiseCanExecuteChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }

    public bool CanExecute(T parameter)
    {
        return _canExecute(parameter);
    }

    public void Execute(T parameter)
    {
        _execute(parameter);
    }

    bool ICommand.CanExecute(object parameter)
    {
        if (!IsParameterValidType(parameter))
            return false;

        return CanExecute((T)parameter);
    }

    void ICommand.Execute(object parameter)
    {
        if (!IsParameterValidType(parameter))
            throw new ArgumentException(string.Format("Parameter must be of type {0}", typeof(T)));

        Execute((T)parameter);
    }

    private static bool IsParameterValidType(object parameter)
    {
        if (parameter != null && !typeof(T).IsAssignableFrom(parameter.GetType()))
            return false;

        return true;
    }
}

现在,如果我关闭对话框窗口并在视图模型上的 CanExecute(我使用带有弱事件订阅的 Prism DelegateCommand)方法中设置断点,我注意到尽管对话框已关闭,但它仍会触发.为什么对话框中的按钮和 ViewModel 上的命令之间的绑定还活着?

Now, If I close the dialog window and set a breakpoint in the CanExecute (I'm using Prism DelegateCommand with weak event subscription) method on the viewmodel, I notice that it triggers although the dialog has been closed. Why on earth is the binding between the button in the dialog and the command on the ViewModel still alive?

我正在通过关闭窗口并稍后在视图模型的CanClickMe"方法中设置断点来检查它是否正在执行.它会执行一段时间,然后突然停止(可能是由于 GC).这种非确定性行为会导致问题,因为在实际应用程序中,视图模型可能已经被处理掉了.

And I am checking if its being executed by closing the window and at a later time setting a breakpoint in the "CanClickMe" method in the viewmodel. It will get executed for a while, then suddenly stop (probably due to GC). This non-determenistic behaviour is causing problems because in the real application the viewmodel might already bee disposed.

推荐答案

您可以使用 Wea​​kEvent 模式来缓解此问题.请参考以下 Stackoverflow 问题:Josh Smith 对 RelayCommand 的实现是否有缺陷?

You may use the WeakEvent Pattern to mitigate this problem. Please refer to the following Stackoverflow question: Is Josh Smith's implementation of the RelayCommand flawed?

这篇关于ui 何时与命令分离?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆