简体   繁体   中英

WPF DataBinding, MVVM and Routed Events

When I try to call my UserControl's custom RoutedEvent in my XAML using a Command Delegate binding I get this exception:

Exception thrown: 'System.Windows.Markup.XamlParseException' in PresentationFramework.dll 
Additional information: 'Provide value on 'System.Windows.Data.Binding' threw an exception.'

My WPF application is using MVVM and IOC so all the logic is in the view models.

The DataContext for a view is set in a resource dictionary:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:vw="clr-namespace:MyApp.Order.View"
            xmlns:vm="clr-namespace:MyApp.Order.ViewModel">

<DataTemplate DataType="{x:Type vm:OrderViewModel}">
    <vw:OrderView />
</DataTemplate>

etc

I have a UserControl in another project within this solution that happens to be a Keyboard and I've wired up a routed event like so:

public partial class MainKeyboard : UserControl
{
    public static DependencyProperty TextProperty;
    public static DependencyProperty FirstLetterToUpperProperty;

    // Create a custom routed event by first registering a RoutedEventID
    // This event uses the bubbling routing strategy
    public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
        "Tap", RoutingStrategy.Bubble, 
        typeof(RoutedEventHandler), 
        typeof(MainKeyboard));

    // Provide CLR accessors for the event
    public event RoutedEventHandler Tap
    {
        add { AddHandler(TapEvent, value); }
        remove { RemoveHandler(TapEvent, value); }
    }

    // This method raises the Tap event
    void RaiseTapEvent()
    {
        RoutedEventArgs newEventArgs = new RoutedEventArgs(MainKeyboard.TapEvent);
        RaiseEvent(newEventArgs);
    }

Now, when I consume this event using my XAML declration and bind the Command to the view model's command delegate like I normally do:

  <assets:MainKeyboard           Tap="{Binding DoTapCommandInViewModel}" />

I get an error, but I can do this everywhere else, like in a button right above this code:

  <Button Content="GetStarted" 
                            Command="{Binding DoTapCommandInViewModel}" 
                            Style="{StaticResource GetStartedButton}" />

What does work for me is calling a method in the code behind of this XAML file:

<assets:MainKeyboard Tap="MainKeyboard_OnTap"/>

The datacontext for both the button and the keyboard user control are the same; they live in the same view.

So why can't I bind this event directly to a command?

Dytori was right; I needed an Event Trigger on the control declaration. Ah Wpf...

           <assets:MainKeyboard>
                    <b:Interaction.Triggers>
                        <b:EventTrigger EventName="Tap">
                            <b:InvokeCommandAction Command="{Binding DoTapTapTap}"/>
                        </b:EventTrigger>
                    </b:Interaction.Triggers>
            </assets:MainKeyboard>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM