Laden...

CanExecute verändert trotz "true" nicht den Button

Erstellt von behindyoû vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.618 Views
B
behindyoû Themenstarter:in
20 Beiträge seit 2020
vor 3 Jahren
CanExecute verändert trotz "true" nicht den Button

Guten Mittag. 😃

Ich habe ein kleines Problem mit dem Button hier.
Ich nutze Prism
View

                <StackPanel Orientation="Vertical" HorizontalAlignment="Left">
                    <Label Content="Username:" FontSize="15"/>
                    <TextBox Width="220" Height="25" FontSize="15" Text="{Binding Path=Username, UpdateSourceTrigger=PropertyChanged}"/>
                </StackPanel>

                <StackPanel Orientation="Vertical" HorizontalAlignment="Left">
                    <Label Content="Password:" FontSize="15"/>
                    <TextBox Width="220" Height="25" FontSize="15" Text="{Binding Path=Password, UpdateSourceTrigger=PropertyChanged}"/>
                </StackPanel>
                <Button Content="Login" Margin="5" FontSize="14" Height="28" Command="{Binding LoginCommand}"/>

ViewModel


LoginCommand = new DelegateCommand(LoginAction, CanLoginExecute);

Vorerst soll der Button nur Enable sein, wenn die Werte der TextBox nicht leer sind

        private bool CanLoginExecute()
        {

            return !string.IsNullOrWhiteSpace(password) && !string.IsNullOrWhiteSpace(username);
            
        }

Trotz richtigen Werten wird der Button nicht geupdatet und Klickbar gemacht.
Weiß einer vielleicht wo mein Fehler ist ?
Liegt es eventuell an Prism, oder gar an dem DelegateCommand, dass er das nicht triggert? ich weiß mir leider auch kein Rat mehr 😕

16.807 Beiträge seit 2008
vor 3 Jahren

Dein CanExecute ist falsch implementiert; siehe [Artikel] MVVM und DataBinding Abschnitt Commands.

Dir fehlt die Parametrisierung sowie das Delegate dahinter.

4.931 Beiträge seit 2008
vor 3 Jahren

@Abt: Das paßt schon so bei Prism, s. Commanding (es wird hier die nicht-generische Variante des DelegateCommand benutzt - sonst würde es ja auch nicht kompilieren).

Man muß RaiseCanExecuteChanged aufrufen, sobald sich der Wert (bzw. einer der Werte), die im CanExecute abgefragt werden, ändern (d.h. man muss daraus Eigenschaften machen und im Setter dann command.RaiseCanExecuteChanged() aufrufen), s.a. WPF-Prism CanExecute method not being called.
Oder alternativ ObservesProperty() verwenden...

PS: Ich persönlich mag die Umsetzung mittels des CommandManager nicht (wie sie in dem MVVM-Artikel benutzt wird), da diese einige Nachteile hat, s. z.B. Is the common implementation of RelayCommand violating the MVVM pattern?

B
behindyoû Themenstarter:in
20 Beiträge seit 2020
vor 3 Jahren

Th69: Oh super, vielen lieben dank. 😄
Hätte ich auch kommen können, in dem ich die PrismyLibray mal unter Commands etwas durchforstet hätte 😦 Tut mir leid, für den unnötigen Beitrag.

Hättest du irgendein Anreiz es anders handzuhaben ?

Abt: Vielen dank für die schnelle Antwort.
Ich werde mir den Beitrag trotz der Lösung mal anschauen, kann ja nicht schaden auch für den fall, sollte ich Projekte ohne Prism bearbeiten.

4.931 Beiträge seit 2008
vor 3 Jahren

Hättest du irgendein Anreiz es anders handzuhaben ?

Beziehst du dich auf mein "PS"? Damit wolle ich nur ausdrücken, daß ich die Prism-Variante mittels DelegateCommand (welche man aber auch in Nicht-Prism Projekte einsetzen kann) besser als die RelayCommand-Variante finde. Der Artikel selbst ist aber sehr zu empfehlen und ich weise auch hier im Forum öfters darauf hin. 😉

Läuft es denn jetzt bei dir?

B
behindyoû Themenstarter:in
20 Beiträge seit 2020
vor 3 Jahren

Th69: Ja, es hat wunderbar funktioniert. 😄
Aktuell versuche ich einige Beispiele über die Verbindung zu einer SQLite Datenbank mit dem MVVM-Muster zu finden, irgendwie etwas schwierig nachzuvollziehen, da ich mit den Fachbegriffen nicht so vertraut bin, was genau die in den Artikeln mit dem BusinessLogic meinen, wo genau ich meine Verbindung zur DB aufbaue, wo in dem Architektur ich die Abfragen mache aber versuche mich da irgendwie durch zu kämpfen. 😄

5.657 Beiträge seit 2006
vor 3 Jahren

Man muß RaiseCanExecuteChanged aufrufen, sobald sich der Wert (bzw. einer der Werte), die im CanExecute abgefragt werden, ändern (d.h. man muss daraus Eigenschaften machen und im Setter dann command.RaiseCanExecuteChanged() aufrufen)

Nein, muß man nicht, so ist das nicht gedacht. Stattdessen sollte man den CommandParameter mittels DataBinding festlegen. Dann wird der Status neu überprüft, sobald sich der gebundene Wert ändert. Falls der Status von mehreren Werten abhängig ist, kann man auch (Multi)Trigger verwenden. In allen anderen Fällen kann man den Button auch unabhängig vom Command aktivieren oder deaktivieren.

Weeks of programming can save you hours of planning

4.931 Beiträge seit 2008
vor 3 Jahren

Du meinst schon Prism, oder? Weil in der offiziellen, von mir verlinkten, Doku steht (außer ObservesProperty() bzw. ObservesCanExecute()) keine weitere Alternative.