Double tapped behavior

769 views Asked by At

I have tried to implement a double tapped behavior. The .cs code looks like:

public class DoubleTappedBehavior : Behavior<InputElement>
{
    /// <summary>
    ///     The command.
    /// </summary>
    public static readonly DirectProperty<DoubleTappedBehavior, ICommand> CommandProperty = 
        AvaloniaProperty.RegisterDirect<DoubleTappedBehavior, ICommand>(
            nameof(Command), 
            o => o.Command,
            (o, v) => o.Command = v);

    public ICommand Command
    {
        get { return GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.DoubleTapped += DoubleTapped;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.DoubleTapped -= DoubleTapped;
        base.OnDetaching();
    }

    private void DoubleTapped(object sender, RoutedEventArgs e)
    {
        if (Command == null)
            return;

        Command.Execute(null);
     }
}

The xaml looks like:

<TreeView Items="{Binding Sections, ElementName=ToC, Mode=TwoWay}" 
          SelectedItem="{Binding SelectedSection, ElementName=ToC, Mode=TwoWay}">

  <TreeView.Styles>
    <Style Selector="TreeViewItem">
      <Setter Property="commandBehaviors:DoubleTappedBehavior.Command"
              Value="{Binding IncrementCount}"/>
      <!--<Setter Property="commandBehaviors:DoubleTappedBehavior.CommandParameter"
              Value="{Binding}"/>-->
    </Style>
  </TreeView.Styles>
 </TreeView>

I get the exception: Could not find AvaloniaProperty 'DoubleTappedBehavior.Command'. Is it possible to set it this way?

1

There are 1 answers

4
Eric On

Can't tell the exact packages that you are using, but it looks like you are creating a Blend like behavior whereas the style is trying to set an attached property.

If that is the case then you either need to change your behavior class to use attached properties or set the Interaction.Behaviors property in your style.

Attached Properties:

https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/attached-properties-overview

Using Blend SDK Behavior:

<TreeView Items="{Binding Sections, ElementName=ToC, Mode=TwoWay}" 
      SelectedItem="{Binding SelectedSection, ElementName=ToC, Mode=TwoWay}">
    <i:Interaction.Behaviors>
        <commandBehaviors:DoubleTappedBehavior Command="{Binding IncrementCount}" CommandParameter="{Binding}" />
    </i:Interaction.Behaviors>
</TreeView>

Attached Property Behavior:

public class DoubleTappedBehavior
{
    public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(DoubleTappedBehavior), new PropertyMetadata(null, OnCommandChanged));
    public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached("CommandParameter", typeof(object), typeof(DoubleTappedBehavior), new PropertyMetadata(null));

    private static void OnCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
    {
        var element = target as UIElement;

        if (element != null)
        {
            element.DoubleTapped -= OnDoubleTapped;
            element.DoubleTapped += OnDoubleTapped;
        }
    }

    private static void OnDoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
    {
        var element = sender as UIElement;

        if (element != null)
        {
            var command = GetCommand(element);
            var commandParameter = GetCommandParameter(element);

            if (command != null)
            {
                if (command.CanExecute(commandParameter))
                {
                    command.Execute(commandParameter);       
                }
            }
        }
    }

    public static void SetCommand(UIElement target, ICommand value) => target.SetValue(CommandProperty, value);

    public static ICommand GetCommand(UIElement target) => (ICommand)target.GetValue(CommandProperty);

    public static void SetCommandParameter(UIElement target, object value) => target.SetValue(CommandProperty, value);

    public static object GetCommandParameter(UIElement target) => target.GetValue(CommandParameterProperty);
}