2012-12-12 4 views
12

때로는 복잡한 방법을 여러 번 사용했기 때문에 작업을 수행하는 가장 간단한 방법을 잊어 버렸습니다.WPF에서 명령을 바인딩하는 방법

나는 명령 바인딩을하는 법을 알고 있지만, 나는 항상 같은 접근법을 사용한다.

ICommand 인터페이스를 구현하는 클래스를 만들고 뷰 모델에서 해당 클래스의 새 인스턴스를 만들고 매력처럼 작동합니다.

내가

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this;    
     testCommand = new MeCommand(processor); 
    } 

    ICommand testCommand; 

    public ICommand test 
    { 
     get { return testCommand; } 
    } 
    public void processor() 
    { 
     MessageBox.Show("hello world"); 
    } 
} 

public class MeCommand : ICommand 
{ 
    public delegate void ExecuteMethod(); 
    private ExecuteMethod meth; 
    public MeCommand(ExecuteMethod exec) 
    { 
     meth = exec; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return false; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     meth(); 
    } 
} 

바인딩 명령에 사용되는 코드입니다하지만 난이 작업을 수행 할 수있는 기본적인 방법을 알고 싶어, 더 타사 새로운 클래스 생성을 dll을하지 않습니다. 단일 클래스를 사용하여이 간단한 명령 바인딩을 수행하십시오. 실제 클래스는 ICommand 인터페이스에서 구현하고 작업을 수행합니다.

답변

13

Prism 이미

Microsoft.Practices.Prism.Commands.DelegateCommand를 제공 나는 그것이 제 3 자로 간주 모르겠어요. 적어도 공식적으로 MSDN에 문서화되어 있습니다.

copy, paste와 같은 일부 기본 빌드 명령은 ICommand 인터페이스를 구현합니다. IMHO Open (확장 용)/Close (변경 용) 원칙을 따릅니다. 그래서 우리는 우리 자신의 명령을 구현할 수 있습니다.


WPF 사령관은 here, 발췌을 기록으로 업데이트

...

WPF는 미리 정의 된 명령 세트를 제공합니다. 찾아보기, 찾아보기 및 BrowseForward, Play, Stop 및 Pause를 탐색하십시오.

명령 라이브러리 클래스의 명령이 사용자의 필요에 맞지 않으면 명령을 직접 작성할 수 있습니다. 사용자 지정 명령을 만드는 방법에는 두 가지가 있습니다. 첫 번째는 처음부터 시작하여 ICommand 인터페이스를 구현하는 것입니다. 다른 방법으로 보다 일반적인 접근 방법은, 은 RoutedCommand 또는 RoutedUICommand을 만드는 것입니다.

처음에 RoutedCommand 모델을 시도해 본 결과 ICommand가 구현되었습니다.

<CommandBinding Command="{x:Static custom:Window1.CustomRoutedCommand}" 
        Executed="ExecutedCustomCommand" 
        CanExecute="CanExecuteCustomCommand" /> 

RoutedCommand 결합

샘플은 XAML RoutedEvent 다르지 않다. 이것은 더 나은 버튼의 'Clicked'이벤트 처리기처럼 보입니다. 그것은 용도를 제공합니다 : 뷰에서 애플리케이션 로직을 분리하지만 일부는 DependencyProperty 또는 코드 숨김을 첨부해야합니다.

개인적으로 나는 ICommand를 구현하는 것만으로도 편합니다.

+1

확실히 제 3 자로 간주됩니다. 나는 thirsd 파티에 대한 원한의 어떤 종류도 가지고 있지 않다. GalaSoft MVVM을 사용하고 있지만 간단하고 기본적인 기본적인 실제 방법을 알고 싶습니다. 어쨌든 고마워. – MegaMind

+1

실제로 질문을 읽은 유일한 사람으로 Upvoted. – psycho

+0

@psycho 내 고통을 이해하는 유일한 사람인 것에 대한 건설적인 의견. :-) – MegaMind

0

글쎄, 당신은 거의 가지고있다. CanExecute()가 true를 반환하는지 확인하십시오. 그렇지 않으면 코드가 실행되지 않습니다. (나는 그것이 실제로 할 것이다라고 생각한다. 그러나 조용함).또한 "NotifyPropertyChanged ('yourCommand')"를

public ICommand test 
    { 
     get { return testCommand; } 
     set { testCOmmand = value; NotifyPropertyChanged("test"); } 
    } 

여기에 추가하십시오.

test = new MeCOmmand(); DataContext = this; 당신은 VS에서 코드를 실행하지 않고 무엇으로 판단

+0

이 명령을 실행할 때 실행할 방법은 어디에 있습니까? 그리고 섹션에서 당신은 MeCommand 클래스를 사용하는 것을 말하고 있습니다. 그러나 제가 언급 한 것처럼 임의의 커스텀 클래스를 사용하고 싶지는 않습니다. – MegaMind

+0

이미 말했듯이, 명령 시스템은 WPF에 의해 위임되고 당신은 그것을 변경할 수 없습니다. RelayCommand/DelegateCommand와 같은 구현이 있지만 명령을 사용하려면 ICommand 인터페이스를 구현해야합니다. 그 정도로. 직접 메소드를 실행하려면 이벤트 사용을 시작하십시오. –

+0

당신은 단지 당신이 당신의 질문에 자신을 분명히하지 않았기 때문에 Downvote. 좋지 않은 스타일. –

1

, 당신의 문제는 InitializeComponent이 (XAML 렌더링), 다음 값이 test 속성에있는 마지막 개인 회원을 설정하지 않고 DataContext을 설정 전화 것입니다. 당신의 Command가 더 이상 null이 아니라는 사실을 UI가 어떻게 알아 내야할까요? (그것은 Property에서 발견 된 마지막 값이었습니다)?

은 왜 그렇게처럼 유유히 명령을 실체화하지 :

public ICommand test 
{ 
    get 
    { 
     if(testCommand== null) 
     { 
     testCommand= new MeCommand(processor); 
     } 
     return testCommand; 
    } 
} 

이 필요한 것 및 (런타임에 나중에 그 명령을 변경하지 않는 한) 당신이 변경 통지를 필요로하지 않는 한 그것은 곧있을 것입니다 그런 식으로.

1) CanExecute()가 false를 반환합니다 : 당신의 비즈니스 사례에 따라 true를 반환하거나 평가하는 방식으로

, 당신은 어떤 코드가 명령 바인딩 시나리오에서 실행되고 있지 느낌을 얻을 몇 점이있다 .

2) CanExecute의 조건이 변경되어 true를 반환하지만 호출되지 않습니다. Command를 CommandManager 클래스와 연결할 수 있습니다 (here 참조). 시도하기 전에 1) 해결되었는지 확인하십시오. 이렇게하면 UI에서 CanExecute을 자주 다시 쿼리하고, 아직 충분하지 않은 경우 메서드 CommandManager.InvalidateRequerySuggested()을 명시 적으로 호출합니다.

3) 바인딩이 잘못되었습니다. 과 같이 바인딩 코드를 변경 : 바인딩의 값이 당기거나 밀 때마다

Command="{Binding Path=test, PresentationTraceSources.TraceLevel=High}" 

이것은 당신의 출력 창을 스팸됩니다. "최종 가치 사용"이라는 용어를 찾으십시오. 그것이 null이라면, 당신의 Command는 그것이 있어야 할 곳이 아닙니다 (아직).

+0

제 바인딩이 문제가되지 않습니다. ICommand를 다른 클래스에 구현하지 않고 명령을 바인딩하는 방법을 알고 그 클래스를 사용하기 만하면됩니다. 내 경우에는 MeCommand. – MegaMind

+2

CommandBinding은 ICommand의 구현에서만 작동합니다. WPF 협약이므로 도움을받을 수 없습니다. 아마도 RelayCommand (http://msdn.microsoft.com/en-us/magazine/dd419663.aspx)와 같은 것을 사용하려고 생각할 것입니다. 확인 해봐. –

+2

솔직히, 왜 우리 모두를 downvote? 이것이 지역 사회에 도움이된다고 생각하십니까? –

2

새로운 클래스를 생성하고 싶지 않은 경우 라우트 된 명령을 사용하십시오. 여기 작은 조각이 있습니다. 나는 저장과 같은 라우팅 명령을 생성하고, 윈도우의 결합 명령 button.and 짜잔에서 명령을 높이기 위해 바인딩 한! ..... 나는 이것이 당신에게

public partial class Window1 : Window 
{ 
    public static readonly RoutedCommand Foo = new RoutedCommand(); 

    public Window1() 
    { 
     InitializeComponent(); 
    } 

    void Foo_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
    { 
     // The Window gets to determine if the Foo 
     // command can execute at this time. 
     e.CanExecute = true; 
    } 

    void Foo_Executed(object sender, ExecutedRoutedEventArgs e) 
    { 
     // The Window executes the command logic when the user wants to Foo. 
     MessageBox.Show("The Window is Fooing..."); 
    } 
} 

<Window.CommandBindings> 
<CommandBinding 
    Command="{x:Static local:Window1.Foo}" 
    CanExecute="Foo_CanExecute" 
    Executed="Foo_Executed" 
    /> 

내가 도움이 될 수 있습니다 희망 당신의 문제를 잘 이해하기를 바랍니다.

추 신 : 명령 설계 패턴의 필요성은 command와 실행자의 논리를 분리하는 것입니다. 명령 클래스는 논리를 캡슐화하는 방법입니다.

3

RelayCommand가 내장 된 MVVM 라이트 프레임 워크를 사용하는 경향이 있습니다.

당신은 다음에 relaycommand을 할당, 뷰 모델에 ICommand의 속성을 추가 : -

ICommand ClickMeCommand {get;set;} 
private void InitCommands() 
{ 
    ClickMeCommand = new RelayCommand(()=>HasBeenClicked=true); 
    //or 
    ClickMeCommand = new RelayCommand(ClickMeEvent); 
} 
public void ClickMeEvent() 
{ 
    HasBeenClicked=true; 
} 

을 XAML에서 그냥 일반 바인딩을 사용 : - WPF 창에서

<Button Content='Push me' Command='{Binding ClickMeCommand}' /> 
0

을 생성자를 사용하여 키보드 단축키를 연결하고 대리자가있는 바인딩을 추가 한 다음이를 키 제스처와 연결하면됩니다.

public YourWindow() //your constructor 
{ 
    ... 
    //bind keyboard command shortcuts 
    InputBindings.Add(new KeyBinding(//add a new key-binding, bind it to your command object which takes a delegate 
     new WindowCommand(this) 
     { 
     ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate 
     }, new KeyGesture(Key.P, ModifierKeys.Control))); 
    ... 
} 

그것에 설정 한 방법을 해고하는 실행 대리자를 취하는 간단한 WindowCommand 클래스를 만듭니다.

public class WindowCommand : ICommand 
{ 
    private MainWindow _window; 
    public Action ExecuteDelegate { get; set; } 

    public WindowCommand(MainWindow window) 
    { 
     _window = window; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 

    public event EventHandler CanExecuteChanged; 

    public void Execute(object parameter) 
    { 
     if (ExecuteDelegate != null) 
     { 
      ExecuteDelegate(); 
     } 
     else 
     { 
      throw new InvalidOperationException(); 
     } 
    } 
}