Как мне заставить ListBox, Canvas и Thumb работать вместе? - PullRequest
1 голос
/ 05 января 2010

Как мне заставить ListBox, Canvas и Thumb работать вместе?

Я пытаюсь повторно использовать логику выбора ListBox вместе с Canvas, который содержит перетаскиваемые большие пальцы.

К сожалению, большой палец, кажется, обрабатывает события мыши, так что нажатие на большой палец не делает выбранный элемент.

Я надеялся, что эти элементы можно заставить работать вместе, не прибегая к обходным путям в процедурном коде. Если кто-нибудь знает, возможно ли это или как это сделать, пожалуйста, сообщите мне.

Ниже приведены примеры кодов.

В XAML я определяю ListBox и указываю Canvas в качестве ItemsPanel:

<Window x:Class="ListBoxCanvasThumb.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    Loaded="Window_Loaded"
    >
    <Grid>
        <ListBox
            x:Name="listBox"
            >
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>                
                    <Canvas />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>
    </Grid>
</Window>

В обработчике событий Loaded я создаю перетаскиваемый Thumb, оборачиваю его в ListBoxItem, устанавливаю положение в Canvas и затем добавляю его в ListBox:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    Thumb t = new Thumb();
    t.Width = 10;
    t.Height = 10;
    t.DragDelta += new DragDeltaEventHandler(thumb_DragDelta);

    ListBoxItem i = new ListBoxItem();
    Canvas.SetLeft(i, 10);
    Canvas.SetTop(i, 10);
    i.Content = t;

    listBox.Items.Add(i);
}

В обработчике событий DragDelta я обновляю позицию элемента в Canvas:

void thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
    ListBoxItem i = (ListBoxItem)((Thumb)sender).Parent;
    Canvas.SetLeft(i, Canvas.GetLeft(i) + e.HorizontalChange);
    Canvas.SetTop(i, Canvas.GetTop(i) + e.VerticalChange);
}

Ответы [ 3 ]

3 голосов
/ 21 января 2010

Для этой цели использование элемента управления Thumb на самом деле не так уж и дорого вам, и оно несколько противоречит тому, что вы пытаетесь сделать. Я бы избавился от этого.

Очень просто сделать ваши элементы перетаскиваемыми без Thumb, просто перехватывая события мыши вниз, движения мыши и вверх мыши:

  • Удерживая кнопку мыши, установите флажок «перетаскивания», отметьте текущую позицию и захватите мышь
  • При перемещении мыши, если «перетаскивание» является истинным, обновите Canvas.Left и Canvas.Top на разницу между положением мыши на элементе управления и исходным положением
  • При наведении мыши снимите флажок «перетаскивания» и снимите захват мыши

При этом Thumb не будет перехватывать щелчки клавиатуры и мыши и портить ваш ListBox.

1 голос
/ 21 января 2010

Вы можете попробовать переместить Thumb в шаблон ListBoxItem и использовать состояние фокуса Thumb для запуска выбора. По умолчанию большой палец не фокусируется, но вы можете включить его.

         <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Canvas.Left" Value="10" />
                <Setter Property="Canvas.Top" Value="10" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListBoxItem}">
                            <Border x:Name="Bd" ...>
                                <DockPanel>
                                    <Thumb x:Name="dragger" DockPanel.Dock="Top" 
                                           Width="50" Height="20" Focusable="True"/>
                                    <ContentPresenter/>
                                </DockPanel>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger SourceName="dragger" Property="IsFocused" Value="True">
                                    <Setter Property="IsSelected" Value="True" />
                                </Trigger>

...

1 голос
/ 05 января 2010

Я не знаю, удовлетворит ли это ваше требование не использовать процедурный код, так как, очевидно, вы уже (или это был только пример воспроизведения)

В любом случае, добавьте обработчик к ListBoxItem для PreviewMouseDown и выберите элемент там:

i.PreviewMouseDown += new MouseButtonEventHandler(LBI_PreviewMouseDown);

void LBI_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    var lbi = (ListBoxItem)sender;
    lbi.IsSelected = true;
    lbi.Focus();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...