programing tip

닫기 명령을 단추에 바인딩하는 방법

itbloger 2020. 11. 29. 10:02
반응형

닫기 명령을 단추에 바인딩하는 방법


가장 쉬운 방법은 ButtonClick이벤트 핸들러 를 구현 하고 Window.Close()메서드를 호출 하는 것입니다.하지만 Command바인딩을 통해 어떻게 할까요?


실제 시나리오에서는 단순한 클릭 처리기가 지나치게 복잡한 명령 기반 시스템보다 낫다고 생각하지만 다음과 같이 할 수 있습니다.

이 문서에서 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}}}"/>

약간의 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 문서 에서 수정 됨 )


사실, 그것은 이다 C # 코드없이 가능합니다. 핵심은 상호 작용을 사용하는 것입니다.

<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창을 "window"로 설정하고 다음 두 네임 스페이스를 추가하십시오.

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

이를 위해서는 Expression Blend SDK DLL을 프로젝트, 특히 Microsoft.Expression.Interactions.

Blend가없는 경우 여기 에서 SDK를 다운로드 할 수 있습니다 .


내가 아는 가장 간단한 해결책은 IsCancel속성을 닫기의 true 로 설정하는 것입니다 Button.

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

바인딩이 필요하지 않습니다. WPF가 자동으로 수행합니다!

참조 : MSDN Button.IsCancel 속성 .


들어 .NET 4.5 SystemCommands의 클래스 트릭을 할 것입니다 (- Microsoft.Windows.Shell 또는 니콜라스 솔루션 .NET 4.0 사용자는 WPF 셸 확장 구글을 사용할 수 있습니다).

    <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}"/>

Code Behind에서 다음과 같은 핸들러를 구현할 수 있습니다.

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

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

처음에는 이것이 어떻게 작동하는지 이해하는 데 약간의 어려움이 있었기 때문에 실제로 진행되는 일에 대한 더 나은 설명을 게시하고 싶었습니다.

내 연구에 따르면 이와 같은 작업을 처리하는 가장 좋은 방법은 명령 바인딩을 사용하는 것입니다. 무슨 일이 일어나는지 "메시지"가 프로그램의 모든 것에 방송됩니다. 따라서해야 할 일은 CommandBinding. 이것이 본질적으로하는 것은 "이 메시지를들을 때 이것을하십시오"라고 말하는 것입니다.

따라서 질문에서 사용자는 창을 닫으려고합니다. 가장 먼저해야 할 일은가 SystemCommand.CloseWindowCommand방송 될 때 호출 될 함수를 설정하는 것 입니다. 선택적으로 명령 실행 여부를 결정하는 함수를 할당 할 수 있습니다. 예를 들어 양식을 닫고 사용자가 저장했는지 확인합니다.

MainWindow.xaml.cs (또는 기타 코드 숨김)

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

이제 우리는 설정에 사이의 "연결"이 필요 SystemCommands.CloseWindowCommand하고, CloseAppCloseAppCanExecute

MainWindow.xaml (Or anything that implements CommandBindings)

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

You can omit the CanExecute if you know that the Command should be able to always be executed Save might be a good example depending on the Application. Here is a Example:

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

Finally you need to tell the UIElement to send out the CloseWindowCommand.

<Button Command="SystemCommands.CloseWindowCommand">

Its actually a very simple thing to do, just setup the link between the Command and the actual Function to Execute then tell the Control to send out the Command to the rest of your program saying "Ok everyone run your Functions for the Command CloseWindowCommand".

This is actually a very nice way of handing this because, you can reuse the Executed Function all over without having a wrapper like you would with say WinForms (using a ClickEvent and calling a function within the Event Function) like:

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

In WPF you attach the Function to a Command and tell the UIElement to execute the Function attached to the Command instead.

I hope this clears things up...


One option that I've found to work is to set this function up as a Behavior.

The Behavior:

    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();
        }
    }
}

On the XAML Window, you set up a reference to it and bind the Behavior's Close property to a Boolean "Close" property on your ViewModel:

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

So, from the View assign an ICommand to change the Close property on the ViewModel which is bound to the Behavior's Close property. When the PropertyChanged event is fired the Behavior fires the OnCloseTriggerChanged event and closes the AssociatedObject... which is the Window.

참고URL : https://stackoverflow.com/questions/1065887/how-to-bind-close-command-to-a-button

반응형