在drag/drop過程中,我們在判斷出over的元素上是否可以接受drag的東西之後,通常是通過鼠標的樣式簡單告訴用戶這個元素不接受現在drag的內容,但是用戶通常不知道具體的原因,有時候爲了增強客戶體驗,會在over的過程中顯示tooltip來告訴用戶爲什麼不能接受drag的東西或者告訴用戶over的元素是什麼東西,特別是一些繪圖或者其他一些複雜的應用軟件,這種方式比較廣泛。
WPF 給各種控件提供了ToolTip屬性,可以通過設置該屬性的值來決定鼠標Over到控件的時候要顯示什麼內容,但是在Drag的過程中卻不能觸發MouseOver事件,觸發的是DragOver事件,那就需要Popup 來實現該效果,下面是根據自己的經驗來簡單設計了一個Popup控件實現tooltip功能。
1. 在Xaml中增加Popup控件以及進行數據綁定
<Popup x:Name="toolTip" IsOpen="{Binding ShowToolTip, Mode=OneWay}" AllowsTransparency="True"
Placement="Relative" HorizontalOffset="{Binding ToolTipPos.X}" VerticalOffset="{Binding ToolTipPos.Y}">
<TextBlock Foreground="Red" Text="{Binding DragElement.Description}"></TextBlock>
</Popup>
注:在Popup的屬性設置中特別注意Placement的屬性值,詳細信息可以查看MSDN 怎樣設置Placement屬性,2. 在ViewModel中要注意屬性值的計算
private Point _tooltipPos; public Point ToolTipPos { get { return _tooltipPos; } set { if (_tooltipPos == value) return; if (Math.Abs(_tooltipPos.X - 15 - value.X) > 15 || Math.Abs(_tooltipPos.Y - 15 - value.Y) > 15) { // why reduce 15? because if position the popup window to current cursor location, //if mouse moving when drag/drop, the mouse will be on popup window, so the user's experience is not good. _tooltipPos = value; _tooltipPos.Offset(15, 15); RaisePropertyChanged("ToolTipPos"); } } }
注意ToolTipPos的Set值的設置,實際上value是光標當前的位置,爲什麼要對改值Offset(15,15)?主要是爲了在Popup窗口顯示的時候,要保證光標所Over的控件是原來的控件,如果不進行offset,在某些細微移動的過程中可能出現DragOver的對象由原來的控件跟popup窗口之間切換。
private bool _showToolTip;
public bool ShowToolTip
{
get { return _showToolTip; }
set
{
if(_showToolTip == value)
return;
_showToolTip = value;
RaisePropertyChanged("ShowToolTip");
}
}
該屬性決定了Popup窗口是否要顯示,需要在DragOver事件處理函數中進行設置爲True. 在dragover對象的mousemove處理函數中設置該值爲false,保證Popup消失。
3. DragOver的過程中獲取鼠標的位置,設置Popup窗口的target屬性。
this.toolTip.PlacementTarget = this.SelectedEmployees;
this.ToolTipPos = e.GetPosition(SelectedEmployees);
ShowToolTip = true;
注: e 爲dragover過程中參數DragEventArgs e, 在獲取鼠標位置的時候不要用Mouse.GetPosition(IInputElement ),因爲在drag過程中對鼠標是在DragOver事件中管理的, 用Mouse.GetPosition(IInputElement)不能獲得準確的值。