Search code examples
c#wpfitemscontroleventtrigger

How to catch a custom event with Interactivity.EventTrigger


I'm trying to catch my custom event (TextUpdateEvent) with Interactivity.EventTrigger in the way shown below. But this code gives rise to System.ArgumentException with the message that "The event "MyTextBox" was not found in the type "tool:MyTextBox.TextUpdateEvent"." Could you tell me what is wrong with this?

<UserControl x:Class="mynamespace.MyControl"
xmlns:local="clr-namespace:mynamespace"
xmlns:info="clr-namespace:mynamespace.info"
xmlns:tool="clr-namespace:mynamespace.tool"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
<Grid>
    <Border>
        <ItemsControl ItemsSource="{Binding MyItems}" Name="itemsControl">
            <ItemsControl.ItemTemplate>                         
                <DataTemplate DataType="info:MyInfo">                             
                    <StackPanel Orientation="Horizontal">                                  
                        <TextBlock Text="{Binding MyComment}"/>
                        <tool:MyTextBox Text="{Binding MyName}" x:Name="myTextBox">
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="tool:MyTextBox.TextUpdateEvent"
                                                SourceObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type tool:MyTextBox}}}"
                                                SourceName="myTextBox">                         
                                    <ei:CallMethodAction MethodName="UpdateMyInfo" TargetObject="{Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Mode=TwoWay}"/>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </tool:MyTextBox>
                    </StackPanel>                              
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Border>     
</Grid>

namespace mynamespace.tool
{
    //used to judge whether or not the update suceeded
    public delegate bool MyTextBoxUpdateHandler(object sender);

    public partial class MyTextBox : TextBox
    {
        public MyTextBoxUpdateHandler TextUpdateEvent { get; set; }
    }
}

Or, do I need to create a custom trigger to catch my custom event?

public class TextUpdateEventTrigger : EventTriggerBase<MyTextBox>
{
    // I don't know what I should do here,
    // since the event I'd like to catch is not a RoutedEvent.
}

Solution

  • You should change the TextUpdateEvent to an event instead of a property.

    public event MyTextBoxUpdateHandler TextUpdateEvent;
    

    Since you're calling a method in code-behind you also do not need to attach Interaction triggers:

    <tool:MyTextBox 
        x:Name="myTextBox" 
        Text="{Binding MyName}" 
        TextUpdateEvent="UpdateMyInfo" />
    

    The DataContext Property does not need to be bound on the UserControl itself, because it's already a partial class of the UserControl, you can remove that too.