如何让ListBox,Canvas和Thumb一起工作?

时间:2010-01-05 10:09:23

标签: c# wpf wpf-controls

如何让ListBox,Canvas和Thumb一起工作?

我试图将ListBox的选择逻辑与包含可拖动Thumb的Canvas一起重用。

不幸的是,Thumb似乎处理鼠标事件,因此单击Thumb不会使项目被选中。

我希望这些元素能够在不依赖过程代码中的变通方法的情况下协同工作。如果有人知道这是否可行或如何做,请告诉我。

代码示例如下。

在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 个答案:

答案 0 :(得分:3)

出于这个目的,你对Thumb控件的使用实际上并没有给你带来太大的影响,并且它在几个方面与你想要做的事情有冲突。我会摆脱它。

只需拦截鼠标按下,鼠标移动和鼠标移动事件,即可在没有Thumb的情况下使项目可拖动非常简单:

  • 在鼠标按下时,设置“拖动”标记,记下当前位置,然后捕获鼠标
  • 在鼠标移动中,如果“拖动”为真,则通过控件上的鼠标位置与原始位置之间的差异更新Canvas.Left和Canvas.Top
  • 在鼠标向上时,清除“拖动”标志并清除鼠标捕获

通过这样做Thumb不会拦截键盘和鼠标点击并弄乱您的ListBox

答案 1 :(得分:1)

我不知道这是否会满足您不使用程序代码的要求,因为显然您已经是(或者这只是一个复制示例?)

无论如何,为ListBoxItem的{​​{1}}添加一个处理程序并在那里选择项目:

PreviewMouseDown

答案 2 :(得分:1)

您可以尝试将Thumb移动到ListBoxItem模板中,并使用Thumb的焦点状态触发选择。默认情况下,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>

...