有没有办法实现办公室撤销下拉(图像波纹管)? 我的意思是,当用户将鼠标悬停在除第一项以外的项目上时,我想突出显示上一项 我尝试了一些来自FluentRibbon的控件,但到目前为止没有运气..
答案 0 :(得分: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>
其中local
是定义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中的高亮颜色。随意改变它并尝试一下。
答案 1 :(得分: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>