0

有什么方法可以实现诸如办公室撤消下拉(下图)之类的功能?我的意思是,当用户将鼠标悬停在第一个项目以外的项目上时,我想突出显示上一个项目?我尝试了 FluentRibbon 的一些控制,但到目前为止没有运气..

在此处输入图像描述

4

2 回答 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 回答