Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 突出显示列表框中的多个项目_C#_Wpf_Mvvm - Fatal编程技术网

C# 突出显示列表框中的多个项目

C# 突出显示列表框中的多个项目,c#,wpf,mvvm,C#,Wpf,Mvvm,有没有办法实现office撤消下拉列表(下图)之类的功能? 我的意思是,当用户将鼠标移到项目上而不是第一个项目上时,我想突出显示上一个项目? 我试着从FluentRibbon处进行一些控制,但到目前为止运气不佳 我想你需要这样的东西: <ControlTemplate TargetType="ListBoxItem"> <TextBlock Text="{Binding LastOperation}"> <TextBlock.Style>

有没有办法实现office撤消下拉列表(下图)之类的功能? 我的意思是,当用户将鼠标移到项目上而不是第一个项目上时,我想突出显示上一个项目? 我试着从FluentRibbon处进行一些控制,但到目前为止运气不佳


我想你需要这样的东西:

<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>
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);
        }
    }
 private bool IsMouseOverItem(Visual item, Point mouseOverPoint)
    {
        Rect currentDescendantBounds = VisualTreeHelper.GetDescendantBounds(item);
        return currentDescendantBounds.Contains(mouseOverPoint);
    }

我想你需要这样的东西:

<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>
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);
        }
    }
 private bool IsMouseOverItem(Visual item, Point mouseOverPoint)
    {
        Rect currentDescendantBounds = VisualTreeHelper.GetDescendantBounds(item);
        return currentDescendantBounds.Contains(mouseOverPoint);
    }

在大多数情况下,设计这样的控件是在Blend中完成的。但是,如果您不知道如何使用Blend,您仍然可以仅使用XAML和后面的代码获得类似的结果,但是您必须做更多的工作

我们首先创建一个名为
CustomListBoxItem
的类,该类继承自
ListBoxItem
。然后,我们定义一个dependency属性,用于突出显示列表框中的项目:

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>
用于确定光标是否位于项目上的
IsMouseOverItem
helper方法定义如下:

<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>
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);
        }
    }
 private bool IsMouseOverItem(Visual item, Point mouseOverPoint)
    {
        Rect currentDescendantBounds = VisualTreeHelper.GetDescendantBounds(item);
        return currentDescendantBounds.Contains(mouseOverPoint);
    }
最后是
listBox\u 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();
    }

请注意,我在XAML中使用了随机颜色作为突出显示颜色。请随意更改并尝试一下。

在大多数情况下,这样的控件设计是在Blend中完成的。但是,如果您不知道如何使用Blend,您仍然可以仅使用XAML和后面的代码获得类似的结果,但是您必须做更多的工作

我们首先创建一个名为
CustomListBoxItem
的类,该类继承自
ListBoxItem
。然后,我们定义一个dependency属性,用于突出显示列表框中的项目:

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>
用于确定光标是否位于项目上的
IsMouseOverItem
helper方法定义如下:

<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>
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);
        }
    }
 private bool IsMouseOverItem(Visual item, Point mouseOverPoint)
    {
        Rect currentDescendantBounds = VisualTreeHelper.GetDescendantBounds(item);
        return currentDescendantBounds.Contains(mouseOverPoint);
    }
最后是
listBox\u 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();
    }

请注意,我在XAML中使用了随机颜色作为突出显示颜色。请随意更改并尝试一下。

MouseOverIndex和CurrentIndex都是用于此UI的视图模型的属性。您可以使用代码隐藏逻辑将MouseOverIndexNewValue>MouseOverIndexOldValue{MouseOverIndexOldValue=MouseOverIndexNewValue;}MouseOverIndexNewValue和CurrentIndex绑定到另一个DataTrigger,它们都是用于此UI的视图模型的属性。您可以使用代码隐藏逻辑将MouseOverIndexNewValue>MouseOverIndexOldValue{MouseOverIndexOldValue=MouseOverIndexNewValue;}