Home > Net >  WPF Window custom event creating and binding to ICommand
WPF Window custom event creating and binding to ICommand

Time:11-13

This is WPF/MVVM application. There is some code in code behind MainWindow.xaml.cs that should produce custom event and it is required to report the fact (maybe with args) of this event to view model class (MainWindowViewModel.cs).

For ex. I declared RoutedEvent TimerEvent in partial class MainWindow but I can't binding to view model command due to this event not available on xaml code. Error: Timer is not recognized or is not accessible.

How can this problem be solved? Thanks!

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

            var timer = new Timer();
            timer.Elapsed  = new ElapsedEventHandler(OnTimedEvent);
            timer.Interval = 5000;
            timer.Enabled = true;
        }

        private void OnTimedEvent(object sender, ElapsedEventArgs e)
        {
            RaiseTimerEvent();
        }

        // Create a custom routed event
        public static readonly RoutedEvent TimerEvent = EventManager.RegisterRoutedEvent(
            "Timer", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MainWindow));

        // Provide CLR accessors for the event
        public event RoutedEventHandler Timer
        {
            add => AddHandler(TimerEvent, value);
            remove => RemoveHandler(TimerEvent, value);
        }
        
        void RaiseTimerEvent()
        {
            var newEventArgs = new RoutedEventArgs(MainWindow.TimerEvent);
            RaiseEvent(newEventArgs);
        }
    }
<Window x:Class="CustomWindowEvent.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:CustomWindowEvent"
        Title="MainWindow" Height="250" Width="400"
        Timer="{Binding TimerCommand}">   // THIS PRODUCE ERROR Timer is not recognized or is not accessible.

    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>

    <Grid>
        <StackPanel>
            <TextBlock Text="{Binding Title}"/>
            <Button Width="75"
                    Height="24"
                    Content="Run"
                    Command="{Binding RunCommand}"/>
        </StackPanel>
    </Grid>
</Window>

CodePudding user response:

You cannot bind an ICommand property to an event just like that.

When your window raises the command, you might invoke the command programmatically:

void RaiseTimerEvent()
{
    var newEventArgs = new RoutedEventArgs(MainWindow.TimerEvent);
    RaiseEvent(newEventArgs);

    var vm = this.DataContext as MainWindowViewModel;
    if (vm != null)
        vm.TimerCommand.Execute(null);
}

The other option is to use an EventTrigger and an InvokeCommandAction from the Microsoft.Xaml.Behaviors.Wpf package to invoke the command using XAML:

<Window .. xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Timer" >
            <i:InvokeCommandAction Command="{Binding TimerCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Window>

Please refer to this blog post for more information.

  • Related