2015-01-06 7 views
14

Ich habe folgendes in meiner Seite:Disable ToolbarItem Xamarin.Forms

<ContentPage.ToolbarItems> 
    <ToolbarItem Text="Run" Command="{Binding RunCommand}" /> 
</ContentPage.ToolbarItems> 

Der Befehl startet eine Asynchron-Aufgabe. Ich versuche, die Kontrolle, solange die Asynchron-Aufgabe noch zu deaktivieren ausgeführt wird, indem es auf eine boolesche Eigenschaft Bindung wie folgt:

<ContentPage.ToolbarItems> 
    <ToolbarItem Text="Run" Command="{Binding RunCommand}" IsEnabled="{Binding MyBoolProperty}" /> 
</ContentPage.ToolbarItems> 

Mein Problem ist, dass es kein „IsEnabled“ Eigenschaft zu sein scheint für ToolbarItem. Gibt es eine Möglichkeit zu erreichen, was ich mit Xamarin.Forms zu tun versuche?

+0

Hinweis, habe ich versucht, „ToolbarItem“ mit einem „Button“ ersetzt und kläglich gescheitert: „Objekttyp Xamarin.Forms.Button kann nicht Typ Ziel umgewandelt werden: Xamarin.Forms.ToolbarItem“. – LostBalloon

+0

abhängig von der erwarteten Länge Ihrer Operation, wenn Sie es auf dem UI-Thread ausführen, bleibt die Schaltfläche gedrückt. es ist ein hässlicher Hack und du solltest es nicht für den Netzwerkzugriff verwenden, da das deine App für eine sehr lange Zeit sperren kann. –

Antwort

14

Nach der Unterstützung von William und Xamarin konnte ich endlich herausfinden, wie die Funktionalität funktioniert.

Es ist ein wenig kontra intuitiv, wie wir erwarten, die Schaltfläche zu aktivieren/deaktivieren (ToolbarItem), aber wir müssen tatsächlich den Status des Befehls verwalten, der an die Schaltfläche gebunden ist. Sobald wir dieses Muster verstehen, macht es Sinn. Das Command-Objekt vom Typ ICommand hat eine CanExecute-Eigenschaft (danke, William, um es darauf hinzuweisen). Nun möchten Sie nicht direkt auf es zugreifen/es verwenden, es sei denn, es ist tatsächlich zu überprüfen, ob der Befehl ausgeführt werden kann nicht.

überall dort, wo Sie in Ihrem Code für richtig halten, um den Zustand des Befehls zu ändern, müssen Sie die folgende Zeile hinzufügen:

((Command)_myCommand).ChangeCanExecute(); 

Diese Linie wird die CanExecute Eigenschaft zwingt, wird für den angegebenen neu bewertet Befehl.

Ich persönlich entschied, es hinzuzufügen, wo ich die Inaktivität aufspüren, wie es in meiner Anwendung sinnvoll war.

public bool Inactive { 
    get { 
     return _inactive; 
    } 
    set { 
     if (_inactive != value) { 
      _inactive = value; 
      ((Command)_myCommand).ChangeCanExecute(); 
      OnPropertyChanged(); 
     } 
    } 
} 

In der Ansicht gibt es keine Veränderungen festgestellt werden:

<ToolbarItem Text="Run" Command="{Binding MyCommand}" /> 

Nun, wenn Sie das Command-Objekt erstellen ist, wo die große Arbeit wird getan werden. Wir verwenden normalerweise den Konstruktor für einzelne Argumente, wie es allgemein genug ist, und hier definieren wir, was unser Befehl tut. Interessanterweise gibt es auch einen Konstruktor mit zwei Parametern, in dem Sie die Funktion/Aktion angeben können, die den Wert der CanExecute-Eigenschaft bestimmt.

_myCommand = new Command (async() => { 
              Inactive = false; 
              await Run(); 
              Inactive = true; 
             }, 
            () => { 
              return Inactive; 
             }); 


public ICommand MyCommand { 
    get { 
     return _myCommand; 
    } 
} 

Edit: Ich weiß, dass technisch den Wert von Inaktiv zu ändern in Run() passieren soll, aber zu Demonstrationszwecken ...

+1

Mein Code funktioniert nicht mit diesem Beispiel. Dies wirklich deaktivieren Sie die Schaltfläche oder vermeiden Sie einfach, den Code auszuführen? Haben Sie eine vollständige Probe dieser Implementierung? Vielen Dank. – rubStackOverflow

+1

Es tut beides (deaktivieren Sie die Schaltfläche und vermeiden Sie die Ausführung). Auf welcher Plattform bist du? Ich habe auf iOS und Android getestet. Ich weiß auch, dass es ein Problem gab, als die Reihenfolge von ToolbarItem auf Secondary gesetzt wurde, wo Sie den Unterschied zwischen aktiviert oder nicht sehen konnten, aber der Code würde immer noch nicht ausgeführt, wenn deaktiviert. – LostBalloon

+1

Ich habe die Eigenschaftsdeklaration für MyCommand der Antwort hinzugefügt, um die Schleife vollständig zu schließen. – LostBalloon

0

Was ich gelernt habe, in diesen Situationen zu tun ist, wie folgt:

public Command RunCommand 
{ 
    get { return new Command(async() => await OnRunCommand()); } 
}  

private bool _isRunning; 

public async Task OnRunCommand() 
{ 
    if (_isRunning) return; 
    _isRunning = true; 

    // do stuff 

    _isRunning = false; 
} 

Der Nachteil: Das über die Toolbar in ihrem normalen Zustand verlässt und Benutzer können weiterhin darauf tippen.

Die nach oben: Dies wird keine gleichzeitige OnRunCommand Aufgaben, was gut ist.

Wenn Sie die Deaktivierung der Schaltfläche deaktivieren möchten, indem Sie ein deaktiviertes Bild anzeigen, sollten Sie einen Renderer erstellen.

Wenn das Werkzeugleistenelement während der Ausführung der Aufgabe nicht angezeigt werden soll, sollten Sie das Symbolleistenelement von der Seite entfernen und später erneut hinzufügen.

+1

Ja, ich dachte, dass dies eine mögliche "Worst Case" Lösung wäre, aber ich würde es lieber nicht tun Brechen Sie die Benutzererfahrung mit der Schaltfläche. Ich überlegte, ob ich ein Popup geben sollte, das sie auffordert, Geduld zu haben, da die Aufgabe bereits ausgeführt wird, obwohl ich sie lieber deaktivieren könnte. Ich war überrascht über diese grundlegende Unterlassung für einen Gegenstand, der wie ein Knopf wirkt. – LostBalloon

+0

ToolbarItem kann eine IsEnabled BindableProperty in Xamarin Forms 1.3.0 haben, jetzt, wo ich daran denke. Ich würde es versuchen. –

+0

Leider scheint das nicht der Fall zu sein. – LostBalloon

1

Dieses Beispiel zu entfernen, nicht deaktivieren, aber könnte auch nützlich sein, .

ToolbarItem delToolbar;  

    ... 

     delToolbar = new ToolbarItem 
     { 
      Order = ToolbarItemOrder.Primary,     
      Text = "delete",    
      Command = new Command(async() => 
      {          
       ToolbarItems.Remove(delToolbar); 
      }) 
     }; 
     ToolbarItems.Add(delToolbar);