I am trying to define a custom routed event and then bind this routed event to a command in my view model.
The problem is that I get the exception: "InvalidCastException: Unable to cast object of type 'System.Reflection.RuntimeEventInfo' to type 'System.Reflection.MethodInfo'."
The code behind in my user control that defines the custom routed event:
public static readonly RoutedEvent ItemDobleClickEvent = EventManager.RegisterRoutedEvent(
"ItemDobleClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyUSerControl));
// Provide CLR accessors for the event
public event RoutedEventHandler ItemDobleClick
{
add { AddHandler(CItemDobleClickEvent, value); }
remove { RemoveHandler(ItemDobleClickEvent, value); }
}
void RaiseItemDobleClickEvent(MyType? paramItem)
{
// Create a RoutedEventArgs instance.
RoutedEventArgs routedEventArgs = new(routedEvent: ItemDobleClickEvent);
// Raise the event, which will bubble up through the element tree.
RaiseEvent(routedEventArgs);
}
This is the view of the main view, that use the user control:
<local:ucComponentesBaseView x:Name="MyControl" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
ItemDobleClick="{Binding ItemDobleClickCommand}"/>
This is the code in my main view model:
private RelayCommand? _itemDobleClickCommand;
public RelayCommand ItemDobleClickCommand
{
get { return _itemDobleClickCommand ?? (_itemDobleClickCommand = new RelayCommand(param => ItemDobleClickCommandHandler(), param => true)); }
}
private void ItemDobleClickCommandHandler()
{
//TODO
}
I am biding the rest of the commands in this way.
How could I bind a custom routed event to the command in my view model?
Thanks.
You can implement EventToCommandBehavior on your own:
using System.Windows;
using System.Windows.Input;
using Microsoft.Xaml.Behaviors;
namespace WpfApplication1.Behaviors
{
public class EventToCommandBehavior : Behavior<FrameworkElement>
{
public static readonly DependencyProperty RoutedEventProperty = DependencyProperty.Register(
nameof(RoutedEvent),
typeof(RoutedEvent),
typeof(EventToCommandBehavior),
new PropertyMetadata(null));
public RoutedEvent RoutedEvent
{
get => (RoutedEvent)GetValue(RoutedEventProperty);
set => SetValue(RoutedEventProperty, value);
}
public static readonly DependencyProperty WithCommandProperty = DependencyProperty.Register(
nameof(WithCommand),
typeof(ICommand),
typeof(EventToCommandBehavior),
new PropertyMetadata(null));
public ICommand WithCommand
{
get => (ICommand)GetValue(WithCommandProperty);
set => SetValue(WithCommandProperty, value);
}
readonly RoutedEventHandler _handler;
public EventToCommandBehavior()
{
_handler = (s, e) =>
{
var args = e.OriginalSource;
if (WithCommand.CanExecute(args))
{
WithCommand.Execute(args);
}
};
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.AddHandler(RoutedEvent, _handler);
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.RemoveHandler(RoutedEvent, _handler);
}
}
}
Suppose there is CustomButton control that raises custom routed event ConditionalClick. It can be handled with ProcessConditionalClickCommand command in ViewModel using EventToCommandBehavior:
<StackPanel>
<b:Interaction.Behaviors>
<behaviors:EventToCommandBehavior RoutedEvent="controls:CustomButton.ConditionalClick" WithCommand="{Binding ProcessConditionalClickCommand}">
</behaviors:EventToCommandBehavior>
</b:Interaction.Behaviors>
<controls:CustomButton
Content="Click to trigger a custom routed event"
Background="LightGray">
</controls:CustomButton>
</StackPanel>