2013-07-02 104 views
0

有什么办法可以实现像办公室撤消下拉(图像波纹管)? 我的意思是,当用户将鼠标放在第一个以外的项目上时,我想突出显示上一个项目? 我试图从FluentRibbon一些控制,但至今没有运气..高亮列表框中的多个项目

enter image description here

回答

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的点击处理程序的listBox_SelectedChanged事件处理程序:

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高亮颜色。随意更改并试一试。

+0

感谢您的详细解释。 –

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> 
+0

感谢您的回复,但您如何绑定MouseOverIndex? –

+0

MouseOverIndex和CurrentIndex是用于此UI的视图模型的所有属性。您可以将MouseOverIndex绑定到另一个DataTrigger,其中的代码位于逻辑后面,如if(MouseOverIndexNewValue> MouseOverIndexOldValue){MouseOverIndexOldValue = MouseOverIndexNewValue; } – Nathan

相关问题