2008-10-10 25 views
22

我有一個數據綁定到對象集合的列表框。列表框被配置爲顯示每個對象的標識符屬性。我想展示一個工具提示,其中包含特定於該列表框中項目的信息,而不是整個列表框的一個工具提示。如何爲列表框中的每個項目設置不同的工具提示文本?

我在WinForms中工作,並感謝一些有用的博客文章放在一起非常好的解決方案,我想分享。

我很想看看是否有任何其他優雅的解決方案來解決這個問題,或者如何在WPF中完成這項工作。

回答

19

主要有兩個子問題,必須以解決解決這個問題:

  1. 確定哪個項目正在上空盤旋
  2. 獲取MouseHover事件,當用戶一直徘徊在一個火項目,然後移動光標在列表框中並懸停在另一個項目上。

第一個問題是相當簡單的解決。通過調用喜歡你的處理程序MouseHover中的以下方法,你可以決定哪些項目正在上空盤旋:

private ITypeOfObjectsBoundToListBox DetermineHoveredItem() 
    { 
     Point screenPosition = ListBox.MousePosition; 
     Point listBoxClientAreaPosition = listBox.PointToClient(screenPosition); 

     int hoveredIndex = listBox.IndexFromPoint(listBoxClientAreaPosition); 
     if (hoveredIndex != -1) 
      return listBox.Items[hoveredIndex] as ITypeOfObjectsBoundToListBox; 
     else 
      return null;   
    } 

然後使用返回值來設置工具提示需要。

第二個問題是,通常MouseHover事件不會再次觸發,直到光標離開控件的客戶區,然後再回來。

您可以通過包裝TrackMouseEvent Win32API調用來解決此問題。在下面的代碼中,ResetMouseHover方法包裝API調用以獲得所需的效果:重置控制何時觸發懸停事件的底層計時器。

public static class MouseInput 
{ 
    // TME_HOVER 
    // The caller wants hover notification. Notification is delivered as a 
    // WM_MOUSEHOVER message. If the caller requests hover tracking while 
    // hover tracking is already active, the hover timer will be reset. 

    private const int TME_HOVER = 0x1; 

    private struct TRACKMOUSEEVENT 
    { 
     // Size of the structure - calculated in the constructor 
     public int cbSize; 

     // value that we'll set to specify we want to start over Mouse Hover and get 
     // notification when the hover has happened 
     public int dwFlags; 

     // Handle to what's interested in the event 
     public IntPtr hwndTrack; 

     // How long it takes for a hover to occur 
     public int dwHoverTime; 

     // Setting things up specifically for a simple reset 
     public TRACKMOUSEEVENT(IntPtr hWnd) 
     { 
      this.cbSize = Marshal.SizeOf(typeof(TRACKMOUSEEVENT)); 
      this.hwndTrack = hWnd; 
      this.dwHoverTime = SystemInformation.MouseHoverTime; 
      this.dwFlags = TME_HOVER; 
     } 

    } 

    // Declaration of the Win32API function 
    [DllImport("user32")] 
    private static extern bool TrackMouseEvent(ref TRACKMOUSEEVENT lpEventTrack); 

    public static void ResetMouseHover(IntPtr windowTrackingMouseHandle) 
    { 
     // Set up the parameter collection for the API call so that the appropriate 
     // control fires the event 
     TRACKMOUSEEVENT parameterBag = new TRACKMOUSEEVENT(windowTrackingMouseHandle); 

     // The actual API call 
     TrackMouseEvent(ref parameterBag); 
    } 

}

有了包裝,你可以簡單地調用ResetMouseHover(listBox.Handle)在您的MouseHover處理程序結束,甚至當光標停留在內部控制的懸停事件將再次觸發界限。

我確定這種方法將所有代碼都放在MouseHover處理程序中必須導致更多的MouseHover事件觸發,而不是真正必要的,但它會完成工作。任何改進都比歡迎。

+0

感謝您的修訂建議@reformed。評論者拒絕了它,但我對你覺得困惑的語言進行了調整。 – 2014-08-06 14:09:13

6

我認爲最好的選擇,因爲你的數據綁定你的列表框的對象,將使用 數據模板。所以,你可以做這樣的事情:

<ListBox Width="400" Margin="10" 
     ItemsSource="{Binding Source={StaticResource myTodoList}}"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Path=TaskName}" 
         ToolTipService.ToolTip="{Binding Path=TaskName}"/> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

當然你更換的ItemsSource以您的綁定源是結合,並與在列表中的對象的任何公共財產的結合路徑部分你真的想顯示。 更多詳細信息請參閱msdn

+2

這個問題針對的是WinForms,而不是WPF。 – 2014-03-20 14:11:05

0

使用title屬性,我們可以爲列表框中的每個列表項目設置工具提示。

對列表框中的所有項目進行循環。

ListItem li = new ListItem("text","key"); 
li.Attributes.Add("title","tool tip text"); 

希望這會有所幫助。

+0

僅當打開選擇列表框時才顯示工具提示。具有諷刺意味的是,這對我來說工作正常,我已經使用了這個解決方案,非常感謝。 – 2015-05-06 15:28:34

-1

這是一種使用ListBox創建一組RadioButton的Style。所有這些都是綁定MVVM的。 MyClass包含兩個字符串屬性:MyName和MyToolTip。這將顯示RadioButton的列表,包括正確的ToolTip-ing。這個線程感興趣的是Setter for ToolTip,使其成爲所有Xaml解決方案。

實例:

列表框形式= 「{StaticResource的radioListBox}」 的ItemsSource = 「{結合MyClass的}」 的SelectedValue = 「{結合SelectedMyClass}」/>

風格:

<Style x:Key="radioListBox" TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}"> 
    <Setter Property="BorderThickness" Value="0" /> 
    <Setter Property="Margin" Value="5" /> 
    <Setter Property="Background" Value="{x:Null}" /> 
    <Setter Property="ItemContainerStyle"> 
     <Setter.Value> 
      <Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="ListBoxItem"> 
          <Grid Background="Transparent"> 
           <RadioButton Focusable="False" IsHitTestVisible="False" IsChecked="{TemplateBinding IsSelected}" Content="{Binding MyName}"/> 
          </Grid> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
       <Setter Property="ToolTip" Value="{Binding MyToolTip}" /> 
      </Style> 
     </Setter.Value> 
    </Setter> 
</Style> 
+1

這個問題針對的是WinForms,而不是WPF。 – 2014-03-20 14:11:37

+4

當我發佈這個問題時,StackOverflow將自己描述爲圍繞問題組織的維基。實際上,在我的問題中,「我很想看看是否有任何其他優雅的解決方案來解決這個問題,或者如何在WPF中完成這項工作。「我無法評估此WPF解決方案的正確性,但不需要簡單地因爲它不是WinForms – 2014-04-01 18:40:42

13

使用MouseMove事件,可以跟蹤鼠標移出的項目的索引,並將其存儲在一個變量中,該變量在MouseMoves之間保持其值。每次觸發MouseMove時,它都會檢查索引是否已更改。如果是這樣,它會禁用工具提示,更改此控件的工具提示文本,然後重新激活它。

下面是一個示例,其中Car類的單個屬性顯示在列表框中,但當懸停在任意一行時顯示完整信息。爲了使這個例子能夠工作,你需要的是一個名爲lstCars的ListBox,它帶有一個MouseMove事件和一個名爲tt1的ToolTip文本組件,在你的WinForm中。汽車類的

定義:

class Car 
    { 
     // Main properties: 
     public string Model { get; set; } 
     public string Make { get; set; } 
     public int InsuranceGroup { get; set; } 
     public string OwnerName { get; set; } 
     // Read only property combining all the other informaiton: 
     public string Info { get { return string.Format("{0} {1}\nOwner: {2}\nInsurance group: {3}", Make, Model, OwnerName, InsuranceGroup); } } 
    } 

表加載事件:

private void Form1_Load(object sender, System.EventArgs e) 
    { 
     // Set up a list of cars: 
     List<Car> allCars = new List<Car>(); 
     allCars.Add(new Car { Make = "Toyota", Model = "Yaris", InsuranceGroup = 6, OwnerName = "Joe Bloggs" }); 
     allCars.Add(new Car { Make = "Mercedes", Model = "AMG", InsuranceGroup = 50, OwnerName = "Mr Rich" }); 
     allCars.Add(new Car { Make = "Ford", Model = "Escort", InsuranceGroup = 10, OwnerName = "Fred Normal" }); 

     // Attach the list of cars to the ListBox: 
     lstCars.DataSource = allCars; 
     lstCars.DisplayMember = "Model"; 
    } 

工具提示代碼(包括創建稱爲hoveredIndex類級別變量):

 // Class variable to keep track of which row is currently selected: 
     int hoveredIndex = -1; 

     private void lstCars_MouseMove(object sender, MouseEventArgs e) 
     { 
      // See which row is currently under the mouse: 
      int newHoveredIndex = lstCars.IndexFromPoint(e.Location); 

      // If the row has changed since last moving the mouse: 
      if (hoveredIndex != newHoveredIndex) 
      { 
       // Change the variable for the next time we move the mouse: 
       hoveredIndex = newHoveredIndex; 

       // If over a row showing data (rather than blank space): 
       if (hoveredIndex > -1) 
       { 
        //Set tooltip text for the row now under the mouse: 
        tt1.Active = false; 
        tt1.SetToolTip(lstCars, ((Car)lstCars.Items[hoveredIndex]).Info); 
        tt1.Active = true; 
       } 
      } 
     } 
0

使用onmouseover您可以迭代列表中的每個項目並顯示t他ToolTip

onmouseover="doTooltipProd(event,''); 

function doTooltipProd(e,tipObj) 
{ 

    Tooltip.init(); 
     if (typeof Tooltip == "undefined" || !Tooltip.ready) { 
     return; 
     } 
     mCounter = 1; 
    for (m=1;m<=document.getElementById('lobProductId').length;m++) { 

    var mCurrent = document.getElementById('lobProductId').options[m]; 
     if(mCurrent != null && mCurrent != "null") { 
      if (mCurrent.selected) { 
       mText = mCurrent.text; 
       Tooltip.show(e, mText); 
       } 
     } 
    } 
} 
0

您可以使用它使用的ListBox中的WinForms中的OnMouseMove事件這個簡單的代碼:

private void ListBoxOnMouseMove(object sender, MouseEventArgs mouseEventArgs) 
{ 
     var listbox = sender as ListBox; 
     if (listbox == null) return; 

     // set tool tip for listbox 
     var strTip = string.Empty; 
     var index = listbox.IndexFromPoint(mouseEventArgs.Location); 

     if ((index >= 0) && (index < listbox.Items.Count)) 
      strTip = listbox.Items[index].ToString(); 

     if (_toolTip.GetToolTip(listbox) != strTip) 
     { 
      _toolTip.SetToolTip(listbox, strTip); 
     } 
} 

當然,你必須初始化在構造函數或一些初始化函數工具提示對象:

_toolTip = new ToolTip 
{ 
      AutoPopDelay = 5000, 
      InitialDelay = 1000, 
      ReshowDelay = 500, 
      ShowAlways = true 
}; 

享受!

相關問題