Когда пользовательский интерфейс отделяется от команд?

Я действительно ломаю голову этим. У меня есть главное окно, которое открывает диалог. После закрытия диалогового окна метод CanExecute для команд, связанных в диалоговом окне, все еще выполняется. Это вызывает серьезные проблемы в моем приложении.

Пример:

MainWindow имеет кнопку с обработчиком нажатия. Это обработчик события щелчка:

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

В диалоговом окне я привязываю элемент управления элементами к статическому ресурсу в диалоговом окне, и каждый элемент в списке имеет команду:

<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:

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 все еще жива?

И я проверяю, выполняется ли она, закрывая окно и позже устанавливая точку останова в методе "CanClickMe" в модели просмотра. Он будет выполняться какое-то время, затем внезапно остановитесь (вероятно, из-за GC). Это недетерминистское поведение вызывает проблемы, потому что в реальном приложении модель представления уже может быть удалена.

6
задан Lightness Races with Monica 5 December 2011 в 17:46
поделиться