2013-07-02 290 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

相關問題