2017-11-28 7 views
-1

Ich versuche Commanding zu lernen und habe ein einfaches wpf-Projekt eingerichtet, um einen benutzerdefinierten Befehl zu verwenden. Ich habe eine ListBox und einen Button in einem Fenster. Wenn die ListBox den Fokus hat und ein Objekt ausgewählt ist, möchte ich, dass die Schaltfläche aktiviert wird, andernfalls sollte sie deaktiviert werden.So verwenden Sie Befehle, um auf eine ListBox zu reagieren

definiere ich eine CustomCommand in einem separaten CustomCommands Klasse:

Public Shared ReceivedFocus As New RoutedCommand 

und in meinem Fenster Ich stelle es sich wie folgt zusammen:

<CommandBinding 
    Command="{x:Static local:CustomCommands.ReceivedFocus}" 
    CanExecute="CanActivate" 
    Executed="ChangeSelection"> 
</CommandBinding> 

und den Befehl für die List-Box verwenden, wie folgt:

<ListBox 
    x:Name="lstInactive"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger 
      EventName="GotFocus"> 
      <i:InvokeCommandAction 
       Command="{x:Static local:CustomCommands.ReceivedFocus}" 
      </i:InvokeCommandAction> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</ListBox> 

und schließlich ist die CanActivate-Routine:

Private Sub CanActivate(sender As Object, e As CanExecuteRoutedEventArgs) 
     If lstInactive.SelectedIndex >= 0 Then 
      e.CanExecute = True 
     Else 
      e.CanExecute = False 
     End If 
End Sub 

Dies funktioniert nicht. Das Hauptproblem ist, dass ich nicht verstehe, wie man den CanExecute-Wert auf den Button bezieht. Sollte ich den CanExecute-Wert in der CanActivate-Routine ignorieren und stattdessen die Enabled-Eigenschaft des Buttons festlegen? Wenn ja, was ist der Wert des CanExecute-Parameters von CanExecuteRoutedEventArgs?

Ein zweites Problem ist, dass das GotFocus-Ereignis nicht ausgelöst wird, bis ich ein Element in der ListBox ein zweites Mal auswähle.

Oder vielleicht habe ich überhaupt keinen Zugriff auf Commanding und das ist nicht der richtige Ansatz. Dieses kleine Projekt ist an sich nicht wichtig, es soll sicherstellen, dass ich Commanding nach dem Lesen zahlreicher Artikel darüber verstehe, bevor ich anfange, Befehle in "echten" Projekten zu verwenden. Leider ist es in diesem Stadium klar, dass ich es nicht tue.

+0

Wenn Sie ein 'Button' wollen den Befehl des Staates stellen, Sie tatsächlich die' Button.Command' Eigenschaft auf diesen Befehl binden müssen. Ich würde Ihnen empfehlen, Befehle in einem Ansichtsmodell zu erstellen, anstatt statische Referenzen und 'CommandBinding' zu verwenden. Dadurch haben Sie ein gut definiertes Konzept, das die Logik von der Repräsentation trennt. Binden Sie das 'ListBox.SelectedItem' an die Eigenschaft eines Ansichtsmodells und entscheiden Sie im Ansichtsmodell, ob der Befehl ausgeführt werden kann oder nicht. – dymanoid

+0

Was ist die Grundlage für die Abstimmung nach unten? – SezMe

Antwort

0

Dies funktioniert nicht. Das Hauptproblem ist, dass ich nicht verstehe, wie man den CanExecute-Wert auf den Button bezieht.

Bind seine Command Eigenschaft auf den gleichen Befehl:

<Button Content="Button" Command="{x:Static local:CustomCommands.ReceivedFocus}" /> 

Die Button dann aktiviert oder deaktiviert basierend auf dem Wert sein sollte, dass Sie die CanExecute Eigenschaft in Ihrem CanActivate Ereignishandler gesetzt.

Sie möchten wahrscheinlich auch auf das Ereignis SelectionChanged hören. Dies funktioniert wie erwartet:

<StackPanel> 
    <StackPanel.CommandBindings> 
     <CommandBinding 
       Command="{x:Static local:CustomCommands.ReceivedFocus}" 
       CanExecute="CanActivate" 
       Executed="ChangeSelection"> 
     </CommandBinding> 
    </StackPanel.CommandBindings> 

    <ListBox x:Name="lstInactive"> 
     <ListBoxItem>first</ListBoxItem> 
     <ListBoxItem>second</ListBoxItem> 
     <ListBoxItem>third</ListBoxItem> 
     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="SelectionChanged"> 
       <i:InvokeCommandAction Command="{x:Static local:CustomCommands.ReceivedFocus}"> 
       </i:InvokeCommandAction> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
    </ListBox> 

    <Button Content="Button" Command="{x:Static local:CustomCommands.ReceivedFocus}" /> 
</StackPanel> 

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void CanActivate(object sender, CanExecuteRoutedEventArgs e) 
    { 
     e.CanExecute = lstInactive.SelectedIndex >= 0; 
    } 

    private void ChangeSelection(object sender, ExecutedRoutedEventArgs e) 
    { 

    } 
} 
+0

@mm Das funktioniert nicht, da es die Schaltfläche zwingt, denselben Befehl auszuführen, wie ein Element in den Listenfeldern auszuwählen. In meiner App ist die EINZIGE Aktion, die getroffen wird, e.CanExecute von mehreren Tasten auf dem Fenster zu setzen. – SezMe

+0

Ich habe Hilfe von Ihrer Antwort bekommen und habe meinen Code dementsprechend geändert.Ich setze den Befehl der Schaltfläche auf eine andere Routine und richte die Befehle ListBox GotFocus und Selection change ein, um e.CanExecute = True zu setzen. Aus irgendeinem Grund ändert dies die IsEnabled-Schaltflächeneigenschaft immer noch nicht in True. Ich kann den modifizierten Code veröffentlichen, wenn das helfen würde. – SezMe

+0

BTW Ich war mir der Notwendigkeit bewusst, das SelectionChanged-Ereignis der ListBox zu "beobachten". Ich wollte dich nur wissen lassen, dass ich nicht völlig inkompetent bin; es erscheint einfach so. – SezMe

Verwandte Themen