none
CanExecuteCommand Aktualisierung explizit für ein Command triggern RRS feed

  • Frage

  • Hallo!

    Ich möchte die CanExecuteCommand Bedingungs-Aktualisierung explizit für ein Command manuell auslösen.

    CommandManager.InvalidateRequery(myCommand);     // Spezifische CanExecuteCommand-Bedingung aktualisieren

        

    Ist dies möglich?

    Eine (manuelle) Aktualisierung der Bedingung(en) für alle CanExecuteCommands erreiche ich über den CommandManager:

    CommandManager.InvalidateRequerySuggested();     // Alle CanExecuteCommands aktualisieren



    • Bearbeitet perlfred Montag, 3. Mai 2021 13:38
    Montag, 3. Mai 2021 13:15

Antworten

  • Hi,

    nimm:

    ZeitTriggerCommand.RaiseCanExecuteChanged();

    statt:

    OnChanged("ZeitTriggerCommand");

    Ist deine MVVM_Base eine eigene Lib?

    Gruß

    Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    • Als Antwort markiert perlfred Freitag, 7. Mai 2021 10:50
    Mittwoch, 5. Mai 2021 17:54
  • Hi Fred,
    zum Zeitpunkt der Instanziierung des XAML muss in deinem Fall auch ActionCommand zur Verfügung stehen. In deinem Code wird das aber erst später nach der Instanziierung des XAML im Constructor der statischen Ressource VM gemacht, ohne dass dies über OnChanged der Oberfläche mitgeteilt wird. Ändere mal deinen Code wie nachfolgend und es funktioniert.

      public class VM_AutoAktualisierung : MVVM_Base
      {
        // System-Objekte
        private DispatcherTimer Timer1 { get; set; }                                            // Zentralen Timer
        private DateTime Ref_Zeit { get; set; }                                                 // Referenzzeit
    
        // Objekte die an die View gebunden werden
        private string _Lbl_AktZeit;
        public string Lbl_AktZeit
        {
          get { return _Lbl_AktZeit; }
          set { _Lbl_AktZeit = value; OnChanged(nameof(Lbl_AktZeit)); }
        }
    
        private Brush _MyVM_Eigenschaft;
        public Brush MyVM_Eigenschaft
        {
          get { return _MyVM_Eigenschaft; }
          set { _MyVM_Eigenschaft = value; OnChanged(nameof(MyVM_Eigenschaft)); }
        }
    
        public ICommand MyVM_EigenschaftCommand { get => new ActionCommand(MyVM_EigenschaftExecute, MyVM_EigenschaftCanExecute); }       // VM-Eigenschaft ändern Command
    
        private ICommand ZeitTriggerCommand { get=> new ActionCommand(ZeitTriggerExecuted, ZeitTriggerCanExecute); }           // Zeit-Trigger Command
    
    
        public VM_AutoAktualisierung()
        {
          // Timer initalisieren
          Timer1 = new DispatcherTimer();                                                     // Zentralen Timer initalisieren
          Timer1.Tick += new EventHandler(Timer1_Tick);                                       // Timer-Event zuordnen
          Timer1.Interval = new TimeSpan(0, 0, 1);                                              // Intervall auf Standardwert (1s) setzen
          Ref_Zeit = DateTime.Now;                                                            // Referenz-Zeit initalisieren
          MyVM_Eigenschaft = Brushes.Green;
          Timer1.Start();                                                                     // Zentralen Timer starten
        }
    
        private void Timer1_Tick(object sender, EventArgs e)
        {
          Ref_Zeit = DateTime.Now;                                                        // Referenzzeit aktualisieren
          Lbl_AktZeit = Ref_Zeit.ToString("HH:mm:ss");                                    // Zeitanzeige aktualisieren
          MyVM_Eigenschaft = Ref_Zeit.Second % 4 == 0 || Ref_Zeit.Second % 5 == 0 ? Brushes.Red : Brushes.Green;
          OnChanged(nameof(MyVM_EigenschaftCommand));
        }
    
        private void MyVM_EigenschaftExecute(object obj)
        {
          MessageBox.Show("MyVM_EigenschaftCanExecute is Enabled!  :-)");
        }
        private bool MyVM_EigenschaftCanExecute(object arg) { return MyVM_Eigenschaft == Brushes.Red; }
    
    
        private void ZeitTriggerExecuted(object obj) { }
        private bool ZeitTriggerCanExecute(object arg) { return true; }
      }


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks


    • Bearbeitet Peter Fleischer Mittwoch, 5. Mai 2021 20:07
    • Als Antwort markiert perlfred Donnerstag, 6. Mai 2021 09:19
    Mittwoch, 5. Mai 2021 20:04

Alle Antworten

  • Hi Fred,
    nutze eine separate Eigenschaft vom Typ ICommand und löse für diese Eigenschaft ein PropertyChanged aus. Alle Bindungen an diese Eigenschaft werden damit aktualisiert und es wird CanExecute aufgerufen.

    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Montag, 3. Mai 2021 13:44
  • Hallo Peter!

    Wenn ich dich richtig verstanden habe, also eine separate VM-Eigenschaft, die ich in der CanExecute-Bedingung angebe. Da durch den Setter dieser VM-Eigenschaft OnChanged ausgeführt wird, wird CanExecute aktualisiert.

    Danke! Werde ich ausprobieren!

    Montag, 3. Mai 2021 14:29
  • Hallo Peter!

    Ich bin leider noch kein Stück weiter gekommen.

    Wie löse ich denn für ein ICommand ein PropertyChanged Ereignis aus???

    Ich habe mal ein kleines Projekt gemacht, das einen Timer laufen lässt und die Farbe einer Elipse kontinuierlich ändert. Ein ICommand ist an einen Button gebunden und die CanExecute-Methode reagiert/prüft, ob eine bestimmte  Farbe mit einer VM-Farbe übereinstimmt. Wie erwartet reagiert die IsEnabled-Eigenschaft des Button nicht auf die Farbänderung.

    <Window x:Class="Command_Demo.Window1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:Command_Demo"
            mc:Ignorable="d"
            Title="Command Demo" Height="150" Width="300">
        <Window.Resources>
            <local:VM_AutoAktualisierung x:Key="VM" />
        </Window.Resources>
        <StackPanel DataContext="{StaticResource VM}">
            <Label Content="{Binding Lbl_AktZeit}" FontSize="20"/>
            <Canvas Margin="15,0,0,0">
                <Ellipse Width="50" Height="50" Fill="{Binding MyVM_Eigenschaft}" />
            </Canvas>
            <Button Content=" Test " Command="{Binding MyVM_EigenschaftCommand}" Margin="0,15,0,0" HorizontalAlignment="Center"/>
        </StackPanel>
    </Window>

       

    public class VM_AutoAktualisierung : MVVM_Base
    {
        // System-Objekte
        private DispatcherTimer Timer1 { get; set; }                                            // Zentralen Timer
        private DateTime Ref_Zeit { get; set; }                                                 // Referenzzeit
    
        // Objekte die an die View gebunden werden
        private string _Lbl_AktZeit;
        public string Lbl_AktZeit
        {
            get { return _Lbl_AktZeit; }
            set { _Lbl_AktZeit = value; OnChanged(nameof(Lbl_AktZeit)); }
        }
    
        private Brush _MyVM_Eigenschaft;
        public Brush MyVM_Eigenschaft
        {
            get { return _MyVM_Eigenschaft; }
            set { _MyVM_Eigenschaft = value; OnChanged(nameof(MyVM_Eigenschaft)); }
        }
    
        public ICommand MyVM_EigenschaftCommand { get; set; }       // VM-Eigenschaft ändern Command
        private ICommand ZeitTriggerCommand { get; set; }           // Zeit-Trigger Command
    
    
        public VM_AutoAktualisierung()
        {
            // Timer initalisieren
            Timer1 = new DispatcherTimer();                                                     // Zentralen Timer initalisieren
            Timer1.Tick += new EventHandler(Timer1_Tick);                                       // Timer-Event zuordnen
            Timer1.Interval = new TimeSpan(0,0,1);                                              // Intervall auf Standardwert (1s) setzen
            Ref_Zeit = DateTime.Now;                                                            // Referenz-Zeit initalisieren
            MyVM_EigenschaftCommand = new ActionCommand(MyVM_EigenschaftExecute, MyVM_EigenschaftCanExecute);
            ZeitTriggerCommand = new ActionCommand(ZeitTriggerExecuted, ZeitTriggerCanExecute);
            MyVM_Eigenschaft = Brushes.Green;
            Timer1.Start();                                                                     // Zentralen Timer starten
        }
    
        private void Timer1_Tick(object sender, EventArgs e)
        {
            Ref_Zeit = DateTime.Now;                                                        // Referenzzeit aktualisieren
            Lbl_AktZeit = Ref_Zeit.ToString("HH:mm:ss");                                    // Zeitanzeige aktualisieren
            MyVM_Eigenschaft = Ref_Zeit.Second % 4 == 0 || Ref_Zeit.Second % 5 == 0 ? Brushes.Red : Brushes.Green;
            OnChanged("ZeitTriggerCommand");
        }
    
        private void MyVM_EigenschaftExecute(object obj)
        {
           MessageBox.Show("MyVM_EigenschaftCanExecute is Enabled!  :-)");
        }
        private bool MyVM_EigenschaftCanExecute(object arg) { return MyVM_Eigenschaft == Brushes.Red; }
    
    
        private void ZeitTriggerExecuted(object obj)
        {
                
        }
        private bool ZeitTriggerCanExecute(object arg) { return true; }
    }

    Die separate ICommand-Eigenschaft ist ZeitTriggerCommand, aber wie ich diese in der MyVM_EigenschaftCanExecute angeben soll, ist mir schleierhaft.

    Viele Grüße Fred.







    • Bearbeitet perlfred Mittwoch, 5. Mai 2021 13:16
    Mittwoch, 5. Mai 2021 13:03
  • Hi,

    nimm:

    ZeitTriggerCommand.RaiseCanExecuteChanged();

    statt:

    OnChanged("ZeitTriggerCommand");

    Ist deine MVVM_Base eine eigene Lib?

    Gruß

    Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    • Als Antwort markiert perlfred Freitag, 7. Mai 2021 10:50
    Mittwoch, 5. Mai 2021 17:54
  • Hi Fred,
    zum Zeitpunkt der Instanziierung des XAML muss in deinem Fall auch ActionCommand zur Verfügung stehen. In deinem Code wird das aber erst später nach der Instanziierung des XAML im Constructor der statischen Ressource VM gemacht, ohne dass dies über OnChanged der Oberfläche mitgeteilt wird. Ändere mal deinen Code wie nachfolgend und es funktioniert.

      public class VM_AutoAktualisierung : MVVM_Base
      {
        // System-Objekte
        private DispatcherTimer Timer1 { get; set; }                                            // Zentralen Timer
        private DateTime Ref_Zeit { get; set; }                                                 // Referenzzeit
    
        // Objekte die an die View gebunden werden
        private string _Lbl_AktZeit;
        public string Lbl_AktZeit
        {
          get { return _Lbl_AktZeit; }
          set { _Lbl_AktZeit = value; OnChanged(nameof(Lbl_AktZeit)); }
        }
    
        private Brush _MyVM_Eigenschaft;
        public Brush MyVM_Eigenschaft
        {
          get { return _MyVM_Eigenschaft; }
          set { _MyVM_Eigenschaft = value; OnChanged(nameof(MyVM_Eigenschaft)); }
        }
    
        public ICommand MyVM_EigenschaftCommand { get => new ActionCommand(MyVM_EigenschaftExecute, MyVM_EigenschaftCanExecute); }       // VM-Eigenschaft ändern Command
    
        private ICommand ZeitTriggerCommand { get=> new ActionCommand(ZeitTriggerExecuted, ZeitTriggerCanExecute); }           // Zeit-Trigger Command
    
    
        public VM_AutoAktualisierung()
        {
          // Timer initalisieren
          Timer1 = new DispatcherTimer();                                                     // Zentralen Timer initalisieren
          Timer1.Tick += new EventHandler(Timer1_Tick);                                       // Timer-Event zuordnen
          Timer1.Interval = new TimeSpan(0, 0, 1);                                              // Intervall auf Standardwert (1s) setzen
          Ref_Zeit = DateTime.Now;                                                            // Referenz-Zeit initalisieren
          MyVM_Eigenschaft = Brushes.Green;
          Timer1.Start();                                                                     // Zentralen Timer starten
        }
    
        private void Timer1_Tick(object sender, EventArgs e)
        {
          Ref_Zeit = DateTime.Now;                                                        // Referenzzeit aktualisieren
          Lbl_AktZeit = Ref_Zeit.ToString("HH:mm:ss");                                    // Zeitanzeige aktualisieren
          MyVM_Eigenschaft = Ref_Zeit.Second % 4 == 0 || Ref_Zeit.Second % 5 == 0 ? Brushes.Red : Brushes.Green;
          OnChanged(nameof(MyVM_EigenschaftCommand));
        }
    
        private void MyVM_EigenschaftExecute(object obj)
        {
          MessageBox.Show("MyVM_EigenschaftCanExecute is Enabled!  :-)");
        }
        private bool MyVM_EigenschaftCanExecute(object arg) { return MyVM_Eigenschaft == Brushes.Red; }
    
    
        private void ZeitTriggerExecuted(object obj) { }
        private bool ZeitTriggerCanExecute(object arg) { return true; }
      }


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks


    • Bearbeitet Peter Fleischer Mittwoch, 5. Mai 2021 20:07
    • Als Antwort markiert perlfred Donnerstag, 6. Mai 2021 09:19
    Mittwoch, 5. Mai 2021 20:04
  • Hallo Peter!

    Es ist immer sehr viel anschaulicher, wenn man die Lösung am eigenen Code demonstriert bekommt. Vielen Dank für deine Bemühungen!   


    Bei jedem Lesen des BasisCommands wird ein neues Command instanziiert, dessen Command-Methoden auf die Command-Metoden des BasisCommands verweisen.

    Ein Lesen des BasisCommands führt also zum Ausführen eines Commands, welches die CanExecute-Überprüfung des BasisCommands erneut ausführt. 

    public ICommand MyVM_EigenschaftCommand { get => new ActionCommand(MyVM_EigenschaftExecute, MyVM_EigenschaftCanExecute); }  // VM-Eigenschaft ändern Command


    Dadurch reicht es, der Oberfläche mitzuteilen, dass sich das BasisCommand geändert hat.


    OnChanged(nameof(MyVM_EigenschaftCommand));                                     // Indirekt CanExecute aktualisieren

    Auf den zeitlichen Zusammenhang der Instanziierung des Commands wäre ich nie gekommen! Im Constructor des BasisCommands ein Delegaten, der beim Lesen ein neues Command instanziiert! Einfach perfekt.

    Nochmals vielen Dank für die Lösung!!! Ich hätte wahrscheinlich sonst immer alle Commands aktualisieren lassen.


    • Bearbeitet perlfred Donnerstag, 6. Mai 2021 10:19
    Donnerstag, 6. Mai 2021 10:18
  • Hallo Stefan!

    RaiseCanExecute ist aber auch ein sehr interessanter Ansatz!

    Vielleicht aber direkt beim BasisCommand?! Muss ich mir mal in Ruhe ansehen!

    Um deine Frage noch schnell zu beantworten, ja die Basisklasse ist eine Klasse von mir, welche auf Basis einer INotifyPropertyChange-Klasse nur die Methode OnChanged bereitstellt.

    Vielen Dank für deine Antwort!!!

    Donnerstag, 6. Mai 2021 10:29
  • Hi Fred,
    vereinfachen kannst du den Code, wenn du mit CommadParameter arbeitest, z.B. so:

    XAML:

    <Window x:Class="WpfApp1.Window052"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp052"
            mc:Ignorable="d"
            Title="Window052" Height="200" Width="250">
      <Window.Resources>
        <local:VM_AutoAktualisierung x:Key="VM" />
      </Window.Resources>
      <StackPanel DataContext="{StaticResource VM}">
        <Label Content="{Binding Lbl_AktZeit}" FontSize="20"/>
        <Canvas Margin="15,0,0,0">
          <Ellipse Width="50" Height="50" Fill="{Binding MyVM_Eigenschaft}" />
        </Canvas>
        <Button Content=" Test " Command="{Binding Cmd}" CommandParameter="MyVM_Eigenschaft"
                Margin="0,15,0,0" HorizontalAlignment="Center"/>
      </StackPanel>
    </Window>

    Und dazu die Klassen:

    using System;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Threading;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Threading;
    
    namespace WpfApp052
    {
      public class VM_AutoAktualisierung : MVVM_Base
      {
        // System-Objekte
        private DispatcherTimer Timer1 { get; set; }                                            // Zentralen Timer
        private DateTime Ref_Zeit { get; set; }                                                 // Referenzzeit
    
        // Objekte die an die View gebunden werden
        private string _Lbl_AktZeit;
        public string Lbl_AktZeit
        {
          get { return _Lbl_AktZeit; }
          set { _Lbl_AktZeit = value; OnChanged(nameof(Lbl_AktZeit)); }
        }
    
        private Brush _MyVM_Eigenschaft;
        public Brush MyVM_Eigenschaft
        {
          get { return _MyVM_Eigenschaft; }
          set { _MyVM_Eigenschaft = value; OnChanged(nameof(MyVM_Eigenschaft)); }
        }
    
        public ICommand Cmd { get => new ActionCommand(CmdExecute, CanCmdExecute); }
    
        public VM_AutoAktualisierung()
        {
          // Timer initalisieren
          Timer1 = new DispatcherTimer();                                                     // Zentralen Timer initalisieren
          Timer1.Tick += new EventHandler(Timer1_Tick);                                       // Timer-Event zuordnen
          Timer1.Interval = new TimeSpan(0, 0, 1);                                              // Intervall auf Standardwert (1s) setzen
          Ref_Zeit = DateTime.Now;                                                            // Referenz-Zeit initalisieren
          MyVM_Eigenschaft = Brushes.Green;
          Timer1.Start();                                                                     // Zentralen Timer starten
        }
    
        private void Timer1_Tick(object sender, EventArgs e)
        {
          Ref_Zeit = DateTime.Now;                                                        // Referenzzeit aktualisieren
          Lbl_AktZeit = Ref_Zeit.ToString("HH:mm:ss");                                    // Zeitanzeige aktualisieren
          MyVM_Eigenschaft = Ref_Zeit.Second % 4 == 0 || Ref_Zeit.Second % 5 == 0 ? Brushes.Red : Brushes.Green;
          OnChanged(nameof(Cmd));
        }
    
        private void CmdExecute(object obj)
        {
          switch (obj.ToString())
          {
            case "MyVM_Eigenschaft":
              MessageBox.Show("MyVM_EigenschaftCanExecute is Enabled!  :-)");
              break;
            case "???":
    
              break;
            default:
              break;
          }
        }
        private bool CanCmdExecute(object arg)
        {
          switch (arg.ToString())
          {
            case "MyVM_Eigenschaft":
              return MyVM_Eigenschaft == Brushes.Red;
            default:
              return true;
          }
        }
      }
    
      public class MVVM_Base : INotifyPropertyChanged
      {
        public MVVM_Base() => sc = SynchronizationContext.Current;
        SynchronizationContext sc;
        public event PropertyChangedEventHandler PropertyChanged;
        internal void OnChanged([CallerMemberName] string propName = "") =>
          sc.Post(new SendOrPostCallback((p) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName))), null);
      }
    
      public class ActionCommand : ICommand
      {
        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;
        public ActionCommand(Action<object> execute) : this(execute, canExecute: null) { }
        public ActionCommand(Action<object> execute, Predicate<object> canExecute)
        {
          if (execute == null) throw new ArgumentNullException("execute");
          this._execute = execute;
          this._canExecute = canExecute;
        }
        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) => this._canExecute == null ? true : this._canExecute(parameter);
        public void Execute(object parameter) => this._execute(parameter);
        public void RaiseCanExecuteChanged() => this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
      }
    }
    


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Donnerstag, 6. Mai 2021 13:14
  • Hallo Stefan!

    Das RaiseCanExecute ist natürlich auf den Punkt gebracht, die Lösung meines "Problems".

    Allerdings setzt es voraus, dass das PRISM-WPF-Framework (oder MVVM Light oder ähnliche) implementiert ist. Für so ein einfaches Projekt ist das etwas "oversize". Manche Implementierungen rufen im Hintergrund auch nur CommandManager.InvalidateRequerySuggested auf, was ich ja gerade vermeiden wollte.

    Trotzdem Danke! für  deinen Hinweis.

    Fred.

    • Bearbeitet perlfred Freitag, 7. Mai 2021 10:49
    Freitag, 7. Mai 2021 10:46
  • Hallo Peter!

    Wenn das Prinzip, dass ein Lesen des Commands zu einer Überprüfung der CanExecute-Bedingung führt, erst einmal implementiert ist, kann man, so wie du es hier demonstrierst, kreativ die Bedingung(en) auswerten.

    Ich finde der Code ist nicht kürzer, aber! so könnte man ein Command auch für mehrere Bedingungen nutzen und braucht nur in den Commandparameter(n) eine Zuordnungs-Bezeichnung, die man dann in der Command und CanExecute-Methoden auswertet, angeben.  Wird zwar irgendwann auch unübersichtlich, aber für inhaltlich zusammenhängende Commands durchaus nützlich!

    Vielen Dank auch für diese "Erweiterung"!

    Fred.

    <Window x:Class="Command_Demo.Window2"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:Command_Demo"
            mc:Ignorable="d"
            Title="Command-Demo mit Command-Parameter" Height="200" Width="300">
        <Window.Resources>
            <local:VM_AutoAktualisierung2 x:Key="VM2" />
        </Window.Resources>
        <StackPanel DataContext="{StaticResource VM2}" Margin="0,0,0,15">
            <Label Content="{Binding Lbl_AktZeit}" FontSize="20"/>
            <Canvas Margin="15,0,0,0">
                <Ellipse Width="50" Height="50" Fill="{Binding FarbeEllipse}" />
            </Canvas>
            <Button Content=" Trigger auf Rote-Ellipse " Command="{Binding FarbeEllipseCommand}" CommandParameter="Rot" Margin="0,15,0,0" HorizontalAlignment="Center"/>
            <Button Content=" Trigger auf Blaue-Ellipse " Command="{Binding FarbeEllipseCommand}" CommandParameter="Blau" Margin="0,15,0,0" HorizontalAlignment="Center"/>
        </StackPanel>
    </Window>

       

    public class VM_AutoAktualisierung2 : MVVM_Base
    {
        // System-Objekte
        private DispatcherTimer Timer1 { get; set; }                                            // Zentralen Timer
        private DateTime Ref_Zeit { get; set; }                                                 // Referenzzeit
    
        // Objekte die an die View gebunden werden
        private string _Lbl_AktZeit;
        public string Lbl_AktZeit
        {
            get { return _Lbl_AktZeit; }
            set { _Lbl_AktZeit = value; OnChanged(nameof(Lbl_AktZeit)); }
        }
    
        private Brush _FarbeEllipse;
        public Brush FarbeEllipse
        {
            get { return _FarbeEllipse; }
            set { _FarbeEllipse = value; OnChanged(nameof(FarbeEllipse)); }
        }
    
        public ICommand FarbeEllipseCommand 
        { get { return new ActionCommand(FarbeEllipseExecute, FarbeEllipseCanExecute); } }      // VM-Eigenschaft ändern Command
    
        public VM_AutoAktualisierung2()
        {
            // Timer initalisieren
            Timer1 = new DispatcherTimer();                                                     // Zentralen Timer initalisieren
            Timer1.Tick += new EventHandler(Timer1_Tick);                                       // Timer-Event zuordnen
            Timer1.Interval = new TimeSpan(0, 0, 1);                                              // Intervall auf Standardwert (1s) setzen
            Ref_Zeit = DateTime.Now;                                                            // Referenz-Zeit initalisieren
            FarbeEllipse = Brushes.Green;                                                   // 
            Timer1.Start();                                                                     // Zentralen Timer starten
        }
    
        private void Timer1_Tick(object sender, EventArgs e)
        {
            Ref_Zeit = DateTime.Now;                                                            // Referenzzeit aktualisieren
            Lbl_AktZeit = Ref_Zeit.ToString("HH:mm:ss");                                        // Zeitanzeige aktualisieren
            if(Ref_Zeit.Second % 4 == 0 || Ref_Zeit.Second % 5 == 0) FarbeEllipse= Brushes.Red;                         // 4 oder 5 -> Rot
            else FarbeEllipse = Ref_Zeit.Second % 3 == 0 || Ref_Zeit.Second % 4 == 0 ? Brushes.Blue : Brushes.Green;    // 7 oder 8 -> Blau, alles andere Grün
            OnChanged(nameof(FarbeEllipseCommand));                                             // Aktualisierung der CanExecute-Bedingung auslösen
        }
    
        private void FarbeEllipseExecute(object obj)
        {
            switch (obj.ToString())
            {
                case "Rot": MessageBox.Show("Ellipse ist rot.  :-)"); break;
                case "Blau": MessageBox.Show("Ellipse ist blau.  :-))"); break;
                default: break;
            }
        }
    
        private bool FarbeEllipseCanExecute(object arg)
        {
            switch (arg.ToString())
            {
                case "Rot": return FarbeEllipse == Brushes.Red;
                case "Blau": return FarbeEllipse == Brushes.Blue;
                default: return true;
            }
        }
    }

    Das FarbeEllipseCommand wird für die Triggerung der Buttons  verwendet. Welche Farbe kann in den CommandParameter(n) angegeben werden (soweit es auch ausgewertet wird :-) ).

    Interessant auch dein MVVMBase "Erweiterung"!


    • Bearbeitet perlfred Freitag, 7. Mai 2021 14:17 Konkretisierung
    Freitag, 7. Mai 2021 14:12