Вопрос по wpf, wpf-controls – Как привязать команду «Закрыть» к кнопке

56

Самый простой способ - это реализоватьButtonClick обработчик события и вызовWindow.Close() метод, но как это сделать черезCommand связывание?

Ваш Ответ

7   ответов
36

Самое простое из известных мне решений - это установитьIsCancel свойство истинного концаButton:

<Button Content="Close" IsCancel="True" />

Нет необходимости в привязках, WPF сделает это автоматически!

Ссылка:Свойство MSDN Button.IsCancel.

47

Я думаю, что в реальных сценариях простой обработчик кликов, вероятно, лучше, чем слишком сложные системы на основе команд, но вы можете сделать что-то подобное:

используя RelayCommand из этой статьиhttp://msdn.microsoft.com/en-us/magazine/dd419663.aspx

public class MyCommands
{
    public static readonly ICommand CloseCommand =
        new RelayCommand( o => ((Window)o).Close() );
}
<Button Content="Close Window"
        Command="{X:Static local:MyCommands.CloseCommand}"
        CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, 
                           AncestorType={x:Type Window}}}"/>
Error: User Rate Limit Exceededclass WindowCloseCmd : ICommand { public bool CanExecute(object parameter) { return true; } public event EventHandler CanExecuteChanged { add { } remove { } } public void Execute(object wnd) { if (wnd is Window) ((Window)wnd).Close(); } } public static readonly ICommand WindowCloseCommand = new WindowCloseCmd();
0

Один вариант, который я нашел подходящим, состоит в том, чтобы установить эту функцию как Поведение.

Поведение:

    public class WindowCloseBehavior : Behavior<Window>
{
    public bool Close
    {
        get { return (bool) GetValue(CloseTriggerProperty); }
        set { SetValue(CloseTriggerProperty, value); }
    }

    public static readonly DependencyProperty CloseTriggerProperty =
        DependencyProperty.Register("Close", typeof(bool), typeof(WindowCloseBehavior),
            new PropertyMetadata(false, OnCloseTriggerChanged));

    private static void OnCloseTriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behavior = d as WindowCloseBehavior;

        if (behavior != null)
        {
            behavior.OnCloseTriggerChanged();
        }
    }

    private void OnCloseTriggerChanged()
    {
        // when closetrigger is true, close the window
        if (this.Close)
        {
            this.AssociatedObject.Close();
        }
    }
}

В окне XAML вы устанавливаете ссылку на него и привязываете свойство Behavior 's Close к логическому значению & quot; Close & quot; Свойство на вашей ViewModel:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<i:Interaction.Behaviors>
    <behavior:WindowCloseBehavior Close="{Binding Close}" />
</i:Interaction.Behaviors>

Таким образом, в представлении назначьте ICommand для изменения свойства Close в ViewModel, которое связано со свойством Behavior's Close. Когда происходит событие PropertyChanged, поведение запускает событие OnCloseTriggerChanged и закрывает AssociatedObject ..., который является окном.

56

Actually, it is possible without C# code. Ключ должен использовать взаимодействия:

<Button Content="Close">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
      <ei:CallMethodAction TargetObject="{Binding ElementName=window}" MethodName="Close"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</Button>

Для того, чтобы это работало, просто установитеx:Name вашего окна в «окно» и добавьте эти два пространства имен:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

Для этого необходимо добавить DLL Expression Blend SDK в свой проект, в частностиMicrosoft.Expression.Interactions.

Если у вас нет Blend, SDK можно загрузитьВот.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededei:Error: User Rate Limit ExceededMicrosoft.Expression.InteractionsError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
1

Вначале у меня также были проблемы с выяснением того, как это работает, поэтому я хотел опубликовать лучшее объяснение того, что на самом деле происходит.

Согласно моим исследованиям, лучший способ справиться с такими вещами - это использование командных привязок. То, что происходит, является & quot; Сообщение & quot; транслируется на все в программе. Итак, что вы должны сделать, это использоватьCommandBinding, По сути, это говорит: «Когда вы слышите это сообщение, делайте это».

Таким образом, в вопросе пользователь пытается закрыть окно. Первое, что нам нужно сделать, это настроить наши функции, которые будут вызываться, когдаSystemCommand.CloseWindowCommand транслируется. При желании вы можете назначить функцию, которая определяет, должна ли команда выполняться. Примером может быть закрытие формы и проверка, сохранил ли пользователь.

MainWindow.xaml.cs (Or other Code-Behind)

void CloseApp( object target, ExecutedRoutedEventArgs e ) {
    /*** Code to check for State before Closing ***/
    this.Close();
}

void CloseAppCanExecute( object sender, CanExecuteRoutedEventArgs e ) {
    /*** Logic to Determine if it is safe to Close the Window ***/
    e.CanExecute = true;
}

Теперь нам нужно настроить & quot; Соединение & quot; междуSystemCommands.CloseWindowCommand иCloseApp а такжеCloseAppCanExecute

MainWindow.xaml (Or anything that implements CommandBindings)

<Window.CommandBindings>
    <CommandBinding Command="SystemCommands.CloseWindowCommand"
                    Executed="CloseApp"
                    CanExecute="CloseAppCanExecute"/>
</Window.CommandBindings>

Вы можете опустить CanExecute, если знаете, что команда должна выполняться всегда. Сохранение может быть хорошим примером в зависимости от приложения. Вот пример:

<Window.CommandBindings>
    <CommandBinding Command="SystemCommands.CloseWindowCommand"
                    Executed="CloseApp"/>
</Window.CommandBindings>

Наконец, вам нужно указать UIElement, что нужно отправить CloseWindowCommand.

<Button Command="SystemCommands.CloseWindowCommand">

Это на самом деле очень простая вещь, просто настройте связь между Командой и фактической Функцией для Выполнения, затем скажите элементу управления отправлять Команду остальной части вашей программы, говоря: «Хорошо, все запускают ваши Функции для Команды CloseWindowCommand». ,

На самом деле это очень хороший способ справиться с этим, потому что вы можете повторно использовать Исполняемую функцию повсеместно, не имея оболочки, как, например, с WinForms (используя ClickEvent и вызывая функцию в Event Event), например:

protected override void OnClick(EventArgs e){
    /*** Function to Execute ***/
}

В WPF вы присоединяете функцию к команде и говорите UIElement выполнить вместо нее функцию, присоединенную к команде.

Я надеюсь, что это проясняет ситуацию ...

3

ЗаСистемные команды .NET 4.5 класс сделает свое дело (пользователи .NET 4.0 могут использовать WPF Shell Extension google - Microsoft.Windows.Shell или Nicholas Solution).

    <Window.CommandBindings>
        <CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" 
                        CanExecute="CloseWindow_CanExec" 
                        Executed="CloseWindow_Exec" />
    </Window.CommandBindings>
    <!-- Binding Close Command to the button control -->
    <Button ToolTip="Close Window" Content="Close" Command="{x:Static SystemCommands.CloseWindowCommand}"/>

В коде позади вы можете реализовать обработчики, как это:

    private void CloseWindow_CanExec(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    private void CloseWindow_Exec(object sender, ExecutedRoutedEventArgs e)
    {
        SystemCommands.CloseWindow(this);
    }
68

Все, что нужно, это немного XAML ...

<Window x:Class="WCSamples.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Close"
                        Executed="CloseCommandHandler"/>
    </Window.CommandBindings>
    <StackPanel Name="MainStackPanel">
        <Button Command="ApplicationCommands.Close" 
                Content="Close Window" />
    </StackPanel>
</Window>

И немного C # ...

private void CloseCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
    this.Close();
}

(адаптированы изэта статья MSDN)

Преимущество использования команд состоит в том, что они не привязаны к конкретным элементам управления пользовательского интерфейса; Вы можете использовать эту команду, чтобы закрыть приложение с помощью кнопки, пункта меню или даже сочетания клавиш, и все это одной и той же командой. И хотя эти функциональные возможности не относятся к "близким" операции, команды также предоставляют способ автоматического отключения соответствующего управления пользовательским интерфейсом, когда они не могут быть запущены - способ «вставить». отключено, когда в буфере обмена нет текста.
Error: User Rate Limit Exceeded iLemming
Error: User Rate Limit ExceededApplicationCommands.CloseError: User Rate Limit Exceeded

Похожие вопросы