C# 如何让ListBox、Canvas和Thumb一起工作?
如何让ListBox、Canvas和Thumb一起工作 我试图将ListBox的选择逻辑与包含可拖动拇指的画布一起重用 不幸的是,拇指似乎可以处理鼠标事件,因此单击拇指不会使项目处于选中状态 我希望这些元素可以一起工作,而不必求助于程序代码中的变通方法。如果有人知道这是否可能或如何做到,请告诉我 下面是代码示例 在XAML中,我定义ListBox并指定画布作为ItemsPanel:C# 如何让ListBox、Canvas和Thumb一起工作?,c#,wpf,wpf-controls,C#,Wpf,Wpf Controls,如何让ListBox、Canvas和Thumb一起工作 我试图将ListBox的选择逻辑与包含可拖动拇指的画布一起重用 不幸的是,拇指似乎可以处理鼠标事件,因此单击拇指不会使项目处于选中状态 我希望这些元素可以一起工作,而不必求助于程序代码中的变通方法。如果有人知道这是否可能或如何做到,请告诉我 下面是代码示例 在XAML中,我定义ListBox并指定画布作为ItemsPanel: <Window x:Class="ListBoxCanvasThumb.Window1" xmlns
<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>
在DragDelta事件处理程序中,我更新项目在画布中的位置:
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);
}
我不知道这是否会满足您不使用过程代码的要求,因为很明显您已经或者这只是一个复制示例 无论如何,为PreviewMouseDown向ListBoxItem添加一个处理程序,并在其中选择该项:
i.PreviewMouseDown += new MouseButtonEventHandler(LBI_PreviewMouseDown);
void LBI_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var lbi = (ListBoxItem)sender;
lbi.IsSelected = true;
lbi.Focus();
}
我不知道这是否会满足您不使用过程代码的要求,因为很明显您已经或者这只是一个复制示例 无论如何,为PreviewMouseDown向ListBoxItem添加一个处理程序,并在其中选择该项:
i.PreviewMouseDown += new MouseButtonEventHandler(LBI_PreviewMouseDown);
void LBI_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var lbi = (ListBoxItem)sender;
lbi.IsSelected = true;
lbi.Focus();
}
您可以尝试将拇指移动到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>
。。。
您可以尝试将拇指移动到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>
。。。
出于这个目的,使用拇指控件并没有给您带来多少好处,它在几个方面与您正在尝试的操作相冲突。我会把它处理掉的 只需拦截鼠标下移、鼠标移动和鼠标上移事件,就可以轻松拖动项目,无需拇指: 在“鼠标按下”中,设置拖动标志,注意当前位置,然后捕获鼠标 在鼠标移动中,如果拖动为真,则根据控件上鼠标位置与原始位置之间的差异更新Canvas.Left和Canvas.Top 在“鼠标向上”中,清除拖动标志并清除鼠标捕获
通过这样做,Thumb不会截获键盘和鼠标的点击,也不会弄乱列表框。为此,Thumb控件的使用并没有给您带来太多好处,它在多个方面与您的尝试相冲突。我会把它处理掉的 只需拦截鼠标下移、鼠标移动和鼠标上移事件,就可以轻松拖动项目,无需拇指: 在“鼠标按下”中,设置拖动标志,注意当前位置,然后捕获鼠标 在鼠标移动中,如果拖动为真,则根据控件上鼠标位置与原始位置之间的差异更新Canvas.Left和Canvas.Top 在“鼠标向上”中,清除拖动标志并清除鼠标捕获
通过这样做,拇指将不会截获键盘和鼠标的点击,也不会弄乱你的列表框。谢谢你的回答,但这基本上是我已经在做的事情。问题是我想做的远不止这些。例如,实现多个选择和键盘输入左键和右键,以这种方式更改选择将产生更多的程序代码。我开始这样做,但发现自己认为一定有更好的办法!顺便说一句,我在上面加载的Window_中使用的过程代码只是为了说明问题,我的真实代码数据将对象列表绑定到ItemSource,并使用DataTemplate填充列表框。感谢您的回答,但这基本上是我已经在做的事情。问题是我想做的远不止这些。例如,实现多个选择和键盘输入左键和右键,以这种方式更改选择将产生更多的程序代码。我开始这样做,但发现自己认为一定有更好的办法!顺便说一句,我在上面加载的Window_中使用的过程代码只是为了说明问题,我的真实代码数据将对象列表绑定到ItemSource,并使用DataTemplate填充列表框。这对我不起作用。仍然会抑制单击,并且列表框不会选择。你能修好它吗@AshleyDavis?这对我没用。仍然会抑制单击,并且列表框不会选择。你能修好它吗@AshleyDavis?