Как поймать Нажмите на ListboxItem, когда элемент является шаблонным? - PullRequest
2 голосов
/ 21 октября 2010

У меня есть ListBox с установленным ItemsTemplate.

Теперь я хочу поймать Ctrl + щелчок левой кнопкой мыши по ListBoxItem.

Я нашел KeyBoard класс, который должен дать мне ключи-модификаторы.Теперь, как мне получить событие click для ListBoxItem?Еще лучше, как мне связать это с ICommand.

Я нашел несколько кусочков, но не знаю, как их соединить.Кажется, мне может помочь InputBinding или EventSetter.

1 Ответ

4 голосов
/ 21 октября 2010

Ниже приведен простой пример, который обрабатывает Ctrl + PreviewMouseLeftButtonDown, используя EventSetter в стиле ListBoxItem. Это, вероятно, то, что вы хотите.

XAML:

<ListBox>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListBoxItem_PreviewMouseLeftButtonDown"/>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <s:String>Item1</s:String>
    <s:String>Item2</s:String>
    <s:String>Item3</s:String>
    <s:String>Item4</s:String>
</ListBox>

Code-Behind:

void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if ((Keyboard.Modifiers & ModifierKeys.Control) > 0)
    {
        Console.WriteLine((sender as ListBoxItem).Content.ToString());
        e.Handled = false;
    }
}

Чтобы связать его с ICommand, вы можете использовать прикрепленное поведение, такое как поведение EventToCommand, которое обсуждается здесь .

EDIT:

Чтобы ответить на ваш комментарий, обработка Click-события будет немного сложнее для ListBoxItem из-за двух вещей: 1) ListBoxItem не имеет события click и 2) ListBoxItem внутренне обрабатывает некоторые из MouseEvents. Во всяком случае, я придумал смоделированный, прикрепленный ClickEvent, чтобы он работал. Увидеть ниже. Надеюсь, что это работает.

public class AttachedEvents
{
    private static readonly DependencyProperty IsTriggerEnabledProperty =
        DependencyProperty.RegisterAttached("IsTriggerEnabled", typeof(bool), typeof(FrameworkElement), new FrameworkPropertyMetadata(false));

    public static readonly RoutedEvent ClickEvent;

    static AttachedEvents()
    {
        try
        {
            ClickEvent = EventManager.RegisterRoutedEvent("Click",
                                                        RoutingStrategy.Bubble,
                                                        typeof(RoutedEventHandler),
                                                        typeof(FrameworkElement));
        }
        catch (Exception ex)
        { }
    }


    private static void SetIsTriggerEnabled(FrameworkElement element, bool value)
    {
        if (element != null)
        {
            element.SetValue(IsTriggerEnabledProperty, value);
        }
    }

    private static bool GetIsTriggerEnabled(FrameworkElement element)
    {
        return (element != null) ? (bool)element.GetValue(IsTriggerEnabledProperty) : false;
    }

    public static void AddClickHandler(DependencyObject o, RoutedEventHandler handler)
    {
        FrameworkElement element = (FrameworkElement)o;
        element.AddHandler(ClickEvent, handler);
        element.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(SimulatedClick_MouseLeftButtonUp);
        element.PreviewMouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(SimulatedClick_MouseLeftButtonDown);
    }

    public static void RemoveClickHandler(DependencyObject o, RoutedEventHandler handler)
    {
        FrameworkElement element = (FrameworkElement)o;
        element.RemoveHandler(ClickEvent, handler);
        element.MouseLeftButtonUp -= new System.Windows.Input.MouseButtonEventHandler(SimulatedClick_MouseLeftButtonUp);
        element.PreviewMouseLeftButtonDown -= new System.Windows.Input.MouseButtonEventHandler(SimulatedClick_MouseLeftButtonDown);
    }

    static void SimulatedClick_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        FrameworkElement element = (FrameworkElement)sender;
        UpdateIsTriggerSet(element);
        Mouse.Capture(element);
    }

    static void SimulatedClick_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        FrameworkElement element = (FrameworkElement)sender;

        bool isTriggerSet = (bool)element.GetValue(IsTriggerEnabledProperty);

        // update the trigger set flag
        UpdateIsTriggerSet(element);

        //release the mouse capture
        Mouse.Capture(null);

        // if trigger is set and we are still over the element then we fire the click event
        if (isTriggerSet && IsMouseOver(element))
        {
            element.RaiseEvent(new RoutedEventArgs(ClickEvent, sender));
        }

    }

    private static bool IsMouseOver(FrameworkElement element)
    {
        Point position = Mouse.PrimaryDevice.GetPosition(element);
        if (((position.X >= 0.0) && (position.X <= element.ActualWidth)) && ((position.Y >= 0.0) && (position.Y <= element.ActualHeight)))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    private static void UpdateIsTriggerSet(FrameworkElement element)
    {
        Point position = Mouse.PrimaryDevice.GetPosition(element);
        if (((position.X >= 0.0) && (position.X <= element.ActualWidth)) && ((position.Y >= 0.0) && (position.Y <= element.ActualHeight)))
        {
            if (!(bool)element.GetValue(IsTriggerEnabledProperty))
            {
                element.SetValue(IsTriggerEnabledProperty, true);
            }
        }
        else if ((bool)element.GetValue(IsTriggerEnabledProperty))
        {
            element.SetValue(IsTriggerEnabledProperty, false);
        }
    }
}

Пример использования показан ниже. Я не могу установить прикрепленное событие в XAML (я не уверен почему), поэтому мне пришлось сделать обходной путь здесь. Что я делаю, так это жду, пока загрузится ListBoxItem, и присоединю обработчик событий к коду.

XAML:

<ListBox>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <EventSetter Event="Loaded" Handler="OnLoaded"/>
        </Style>
    </ListBox.ItemContainerStyle>
...
</ListBox>

Code-Behind:

void OnLoaded(object sender, RoutedEventArgs e)
{
    AttachedEvents.AddClickHandler((sender as ListBoxItem), HandleClick);
}

void HandleClick(object sender, RoutedEventArgs e) 
{
    if ((Keyboard.Modifiers & ModifierKeys.Control) > 0)
    {
        Console.WriteLine("Ctrl + Clicked!");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...