有什么方法可以实现诸如办公室撤消下拉(下图)之类的功能?我的意思是,当用户将鼠标悬停在第一个项目以外的项目上时,我想突出显示上一个项目?我尝试了 FluentRibbon 的一些控制,但到目前为止没有运气..
问问题
560 次
2 回答
2
在大多数情况下,设计这样的控件是在 Blend 中完成的。但是,如果您不知道如何使用 Blend,您仍然可以仅使用 XAML 和代码隐藏来获得类似的结果,但是您必须做更多的工作。
我们首先创建一个名为的类,该类CustomListBoxItem
继承自ListBoxItem
. 然后,我们定义一个依赖属性,用于高亮列表框中的项目:
public class CustomListBoxItem : ListBoxItem
{
public static readonly DependencyProperty IsVirtuallySelectedProperty =
DependencyProperty.Register("IsVirtuallySelected", typeof(bool),
typeof(CustomListBoxItem),
new PropertyMetadata(false));
public CustomListBoxItem() : base()
{ }
public bool IsVirtuallySelected
{
get { return (bool)GetValue(IsVirtuallySelectedProperty); }
set { SetValue(IsVirtuallySelectedProperty, value); }
}
}
然后我们添加一个列表框并在 XAML 中为它定义一个样式:
<ListBox Name="listBox" MouseMove="listBox_MouseMove" SelectionChanged="listBox_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type local:CustomListBoxItem}">
<Style.Triggers>
<Trigger Property="IsVirtuallySelected" Value="true">
<Setter Property="Background" Value="SkyBlue"/>
</Trigger>
<Trigger Property="IsVirtuallySelected" Value="false">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
wherelocal
是在其中CustomListBoxItem
定义的命名空间。这就是 XAML 部分所需的全部内容,真正的魔力发生在后面的代码中。
事件listBox_MouseMove
处理程序如下所示:
private void listBox_MouseMove(object sender, MouseEventArgs e)
{
bool itemFound = false;
for (int i = 0; i < listBox.Items.Count; i++)
{
var currentItem = listBox.ItemContainerGenerator.ContainerFromIndex(i) as CustomListBoxItem;
if (currentItem == null)
continue;
// Check whether the cursor is on an item or not.
if (IsMouseOverItem(currentItem, e.GetPosition((IInputElement)currentItem)))
{
// Unselect all items before selecting the new group
listBox.Items.Cast<CustomListBoxItem>().ToList().ForEach(x => x.IsVirtuallySelected = false);
// Select the current item and the ones above it
for (int j = 0; j <= listBox.Items.IndexOf(currentItem); j++)
{
((CustomListBoxItem)listBox.Items[j]).IsVirtuallySelected = true;
}
itemFound = true;
break;
}
}
// If the item wasn't found for the mouse point, it means the pointer is not over any item, so unselect all.
if (!itemFound)
{
listBox.Items.Cast<CustomListBoxItem>().ToList().ForEach(x => x.IsVirtuallySelected = false);
}
}
IsMouseOverItem
用于确定光标是否在项目上的辅助方法定义如下:
private bool IsMouseOverItem(Visual item, Point mouseOverPoint)
{
Rect currentDescendantBounds = VisualTreeHelper.GetDescendantBounds(item);
return currentDescendantBounds.Contains(mouseOverPoint);
}
最后是listBox_SelectedChanged
作为 ListBox 的点击处理程序的事件处理程序:
private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Get all the virtually selected items
List<CustomListBoxItem> selectedItems =
listBox.Items.Cast<CustomListBoxItem>().Where(x => x.IsVirtuallySelected).ToList();
if (selectedItems == null || !selectedItems.Any())
return;
// Do something with the selected items
DoCoolStuffWithSelectedItems();
// Unselsect all.
listBox.Items.Cast<CustomListBoxItem>().ToList().ForEach(x => x.IsVirtuallySelected = false);
listBox.UnselectAll();
}
繁荣,我们完成了。我们现在可以在类构造函数中向 ListBox 添加一些项目:
public MainWindow()
{
InitializeComponent();
listBox.Items.Add(new CustomListBoxItem { Content = "hello world!" });
listBox.Items.Add(new CustomListBoxItem { Content = "wpf is cool" });
listBox.Items.Add(new CustomListBoxItem { Content = "today is tuesday..." });
listBox.Items.Add(new CustomListBoxItem { Content = "I like coffee" });
}
请注意,我使用随机颜色作为 XAML 中的突出显示颜色。随意更改它并尝试一下。
于 2013-07-02T18:40:16.357 回答
1
猜猜你需要这样的东西:
<ControlTemplate TargetType="ListBoxItem">
<TextBlock Text="{Binding LastOperation}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger>
<DataTrigger.Binding>
<MultiBinding>
<Binding Path="MouseOverIndex"/>
<Binding Path="CurrentIndex"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" Value="Gold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</ControlTemplate>
于 2013-07-02T16:37:06.683 回答