Jiew Meng
Jiew Meng

Reputation: 88189

How can I have a Click event on ListBoxItem?

Is there a way I can implement Click on a ListBoxItem? There is MouseLeftButtonUp but its not really the same, I can mouse down elsewhere and drag into another ListBoxItem and it still works, minor problem tho, it maybe weird for users tho

Upvotes: 3

Views: 5534

Answers (2)

Fredrik Hedblad
Fredrik Hedblad

Reputation: 84647

I deleted this answer because I realized that this is way to much for this simple task, but then I thought I'll post it anyway in case someone wants to know how to subclass ListBoxItem for whatever reason.

To really get a Click event from a ListBoxItem you'll have to do the following. First subclass ListBoxItem and check MouseEnter, MouseLeave, MouseUp, MouseDown to know when to fire it.

public class ClickableListBoxItem : ListBoxItem
{
    // Register the routed event
    public static readonly RoutedEvent ClickEvent = 
        EventManager.RegisterRoutedEvent( "Click", RoutingStrategy.Bubble, 
        typeof(RoutedEventHandler), typeof(ClickableListBoxItem));

    // .NET wrapper
    public event RoutedEventHandler Click
    {
        add
        {
            AddHandler(ClickEvent, value);
        } 
        remove
        {
            RemoveHandler(ClickEvent, value);
        }
    }

    protected void OnClick()
    {
        RaiseEvent(new RoutedEventArgs(ClickEvent));
    }

    private bool m_isClickable = false;
    private bool m_click = false;
    protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
    {
        m_isClickable = true;
        base.OnMouseEnter(e);
    }
    protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e)
    {
        m_isClickable = false;
        base.OnMouseLeave(e);
    }
    protected override void OnPreviewMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e)
    {
        if (m_click == true)
        {
            OnClick();
        }
        base.OnPreviewMouseLeftButtonUp(e);
    }
    protected override void OnPreviewMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
    {
        if (m_isClickable == true)
        {
            m_click = true;
        }
        base.OnPreviewMouseLeftButtonDown(e);
    }
}

To get the ListBox to use ClickableListBoxItem instead of ListBoxItem we must also subclass ListBox and override GetContainerForItemOverride.

public class ClickableListBox : ListBox
{
    protected override DependencyObject GetContainerForItemOverride() 
    {
        //Use our own ListBoxItem 
        return new ClickableListBoxItem(); 
    }
}

Then we can use this ClickableListBox in Xaml and get the Click event like this. This will work no mather what you put in the ItemTemplate, Buttons, TextBoxes, TextBlocks etc.

<local:ClickableListBox x:Name="c_listBox">
    <local:ClickableListBox.ItemContainerStyle>
        <Style TargetType="{x:Type local:ClickableListBoxItem}">
            <EventSetter Event="Click" Handler="ListBoxItem_Click"/>
        </Style>
    </local:ClickableListBox.ItemContainerStyle>
</local:ClickableListBox>

An easier solution would be to just subclass the Parent container in the ItemTemplate for the ListBoxItem and use the same Mouse routines.

Upvotes: 4

Goblin
Goblin

Reputation: 8022

You could make a new ControlTemplate for the ListBoxItem with something clickable as the root-element (like a Button), handle the click-event on that and place the ContentPresenter inside the 'clickable'?

Upvotes: 2

Related Questions