Poptip.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Controls.Primitives;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Effects;
  10. namespace CustomUI
  11. {
  12. /// <summary>
  13. /// 气泡提示控件
  14. /// </summary>
  15. public class Poptip : Popup
  16. {
  17. #region private fields
  18. private bool mIsLoaded = false;
  19. private AngleBorder angleBorder;
  20. #endregion
  21. #region DependencyProperty
  22. #region PlacementEx
  23. public EnumPlacement PlacementEx
  24. {
  25. get { return (EnumPlacement)GetValue(PlacementExProperty); }
  26. set { SetValue(PlacementExProperty, value); }
  27. }
  28. public static readonly DependencyProperty PlacementExProperty =
  29. DependencyProperty.Register("PlacementEx", typeof(EnumPlacement), typeof(Poptip)
  30. , new PropertyMetadata(EnumPlacement.TopLeft, PlacementExChangedCallback));
  31. private static void PlacementExChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  32. {
  33. Poptip poptip = d as Poptip;
  34. if (poptip != null)
  35. {
  36. EnumPlacement placement = (EnumPlacement)e.NewValue;
  37. switch (placement)
  38. {
  39. case EnumPlacement.LeftTop:
  40. break;
  41. case EnumPlacement.LeftBottom:
  42. break;
  43. case EnumPlacement.LeftCenter:
  44. break;
  45. case EnumPlacement.RightTop:
  46. break;
  47. case EnumPlacement.RightBottom:
  48. break;
  49. case EnumPlacement.RightCenter:
  50. break;
  51. case EnumPlacement.TopLeft:
  52. break;
  53. case EnumPlacement.TopCenter:
  54. poptip.Placement = PlacementMode.Top;
  55. break;
  56. case EnumPlacement.TopRight:
  57. break;
  58. case EnumPlacement.BottomLeft:
  59. break;
  60. case EnumPlacement.BottomCenter:
  61. break;
  62. case EnumPlacement.BottomRight:
  63. break;
  64. default:
  65. break;
  66. }
  67. }
  68. }
  69. #endregion
  70. #region Background
  71. public Brush Background
  72. {
  73. get { return (Brush)GetValue(BackgroundProperty); }
  74. set { SetValue(BackgroundProperty, value); }
  75. }
  76. public static readonly DependencyProperty BackgroundProperty =
  77. DependencyProperty.Register("Background", typeof(Brush), typeof(Poptip), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(109, 129, 154))));
  78. #endregion
  79. #region BorderThickness
  80. public Thickness BorderThickness
  81. {
  82. get { return (Thickness)GetValue(BorderThicknessProperty); }
  83. set { SetValue(BorderThicknessProperty, value); }
  84. }
  85. public static readonly DependencyProperty BorderThicknessProperty =
  86. DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(Poptip), new PropertyMetadata(new Thickness(1)));
  87. #endregion
  88. #region BorderBrush
  89. public Brush BorderBrush
  90. {
  91. get { return (Brush)GetValue(BorderBrushProperty); }
  92. set { SetValue(BorderBrushProperty, value); }
  93. }
  94. public static readonly DependencyProperty BorderBrushProperty =
  95. DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(Poptip), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(204, 206, 219))));
  96. #endregion
  97. #region CornerRadius
  98. public CornerRadius CornerRadius
  99. {
  100. get { return (CornerRadius)GetValue(CornerRadiusProperty); }
  101. set { SetValue(CornerRadiusProperty, value); }
  102. }
  103. public static readonly DependencyProperty CornerRadiusProperty =
  104. DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(Poptip), new PropertyMetadata(new CornerRadius(5)));
  105. #endregion
  106. #endregion
  107. #region Override
  108. protected override void OnInitialized(EventArgs e)
  109. {
  110. base.OnInitialized(e);
  111. this.AllowsTransparency = true;
  112. //this.StaysOpen = false;
  113. UIElement element = this.Child;
  114. this.Child = null;
  115. Grid root = new Grid()
  116. {
  117. Margin = new Thickness(10),
  118. };
  119. #region 阴影
  120. //Border shadow = new Border()
  121. //{
  122. // Background = new SolidColorBrush(Color.FromRgb(255, 255, 255)),
  123. // SnapsToDevicePixels = true,
  124. // UseLayoutRounding = true,
  125. // CornerRadius = new CornerRadius(3),
  126. //};
  127. //DropShadowEffect shadowEffect = new DropShadowEffect()
  128. //{
  129. // BlurRadius = 10,
  130. // Opacity = 0.2,
  131. // ShadowDepth = 0,
  132. // Color = Color.FromRgb(109, 129, 154),
  133. //};
  134. //shadow.SetValue(Border.EffectProperty, shadowEffect);
  135. //root.Children.Add(shadow);
  136. #endregion
  137. #region 设置阴影的边距,防止出现白边
  138. //switch (this.PlacementEx)
  139. //{
  140. // case EnumPlacement.LeftTop:
  141. // case EnumPlacement.LeftBottom:
  142. // case EnumPlacement.LeftCenter:
  143. // shadow.Margin = new Thickness(0, 0, 8, 0);
  144. // break;
  145. // case EnumPlacement.RightTop:
  146. // case EnumPlacement.RightBottom:
  147. // case EnumPlacement.RightCenter:
  148. // shadow.Margin = new Thickness(8, 0, 0, 0);
  149. // break;
  150. // case EnumPlacement.TopLeft:
  151. // case EnumPlacement.TopCenter:
  152. // case EnumPlacement.TopRight:
  153. // shadow.Margin = new Thickness(0, 0, 0, 8);
  154. // break;
  155. // case EnumPlacement.BottomLeft:
  156. // case EnumPlacement.BottomCenter:
  157. // case EnumPlacement.BottomRight:
  158. // shadow.Margin = new Thickness(0, 8, 0, 0);
  159. // break;
  160. // default:
  161. // break;
  162. //}
  163. #endregion
  164. angleBorder = new AngleBorder()
  165. {
  166. Background = this.Background,
  167. CornerRadius = this.CornerRadius,
  168. BorderThickness = this.BorderThickness,
  169. BorderBrush = this.BorderBrush,
  170. };
  171. switch (this.PlacementEx)
  172. {
  173. case EnumPlacement.LeftTop:
  174. angleBorder.Placement = EnumPlacement.RightTop;
  175. break;
  176. case EnumPlacement.LeftBottom:
  177. angleBorder.Placement = EnumPlacement.RightBottom;
  178. break;
  179. case EnumPlacement.LeftCenter:
  180. angleBorder.Placement = EnumPlacement.RightCenter;
  181. break;
  182. case EnumPlacement.RightTop:
  183. angleBorder.Placement = EnumPlacement.LeftTop;
  184. break;
  185. case EnumPlacement.RightBottom:
  186. angleBorder.Placement = EnumPlacement.LeftBottom;
  187. break;
  188. case EnumPlacement.RightCenter:
  189. angleBorder.Placement = EnumPlacement.LeftCenter;
  190. break;
  191. case EnumPlacement.TopLeft:
  192. angleBorder.Placement = EnumPlacement.BottomLeft;
  193. break;
  194. case EnumPlacement.TopCenter:
  195. angleBorder.Placement = EnumPlacement.BottomCenter;
  196. break;
  197. case EnumPlacement.TopRight:
  198. angleBorder.Placement = EnumPlacement.BottomRight;
  199. break;
  200. case EnumPlacement.BottomLeft:
  201. angleBorder.Placement = EnumPlacement.TopLeft;
  202. break;
  203. case EnumPlacement.BottomCenter:
  204. angleBorder.Placement = EnumPlacement.TopCenter;
  205. break;
  206. case EnumPlacement.BottomRight:
  207. angleBorder.Placement = EnumPlacement.TopRight;
  208. break;
  209. default:
  210. break;
  211. }
  212. //在原有控件基础上,最外层套一个AngleBorder
  213. angleBorder.Child = element;
  214. root.Children.Add(angleBorder);
  215. this.Child = root;
  216. }
  217. protected override void OnOpened(EventArgs e)
  218. {
  219. base.OnOpened(e);
  220. if (this.mIsLoaded)
  221. {
  222. return;
  223. }
  224. FrameworkElement targetElement = this.PlacementTarget as FrameworkElement;
  225. FrameworkElement child = this.Child as FrameworkElement;
  226. if (targetElement == null || child == null) return;
  227. switch (this.PlacementEx)
  228. {
  229. case EnumPlacement.LeftTop:
  230. this.Placement = PlacementMode.Left;
  231. break;
  232. case EnumPlacement.LeftBottom:
  233. this.Placement = PlacementMode.Left;
  234. this.VerticalOffset = targetElement.ActualHeight - child.ActualHeight;
  235. break;
  236. case EnumPlacement.LeftCenter:
  237. this.Placement = PlacementMode.Left;
  238. this.VerticalOffset = this.GetOffset(targetElement.ActualHeight, child.ActualHeight);
  239. break;
  240. case EnumPlacement.RightTop:
  241. this.Placement = PlacementMode.Right;
  242. break;
  243. case EnumPlacement.RightBottom:
  244. this.Placement = PlacementMode.Right;
  245. this.VerticalOffset = targetElement.ActualHeight - child.ActualHeight;
  246. break;
  247. case EnumPlacement.RightCenter:
  248. this.Placement = PlacementMode.Right;
  249. this.VerticalOffset = this.GetOffset(targetElement.ActualHeight, child.ActualHeight);
  250. break;
  251. case EnumPlacement.TopLeft:
  252. this.Placement = PlacementMode.Top;
  253. break;
  254. case EnumPlacement.TopCenter:
  255. this.Placement = PlacementMode.Top;
  256. this.HorizontalOffset = this.GetOffset(targetElement.ActualWidth, child.ActualWidth);
  257. break;
  258. case EnumPlacement.TopRight:
  259. this.Placement = PlacementMode.Top;
  260. this.HorizontalOffset = targetElement.ActualWidth - child.ActualWidth;
  261. break;
  262. case EnumPlacement.BottomLeft:
  263. this.Placement = PlacementMode.Bottom;
  264. break;
  265. case EnumPlacement.BottomCenter:
  266. this.Placement = PlacementMode.Bottom;
  267. this.HorizontalOffset = this.GetOffset(targetElement.ActualWidth, child.ActualWidth);
  268. break;
  269. case EnumPlacement.BottomRight:
  270. this.Placement = PlacementMode.Bottom;
  271. this.HorizontalOffset = targetElement.ActualWidth - child.ActualWidth;
  272. break;
  273. }
  274. this.mIsLoaded = true;
  275. }
  276. #endregion
  277. #region private function
  278. private double GetOffset(double targetSize, double poptipSize)
  279. {
  280. if (double.IsNaN(targetSize) || double.IsNaN(poptipSize))
  281. {
  282. return 0;
  283. }
  284. return (targetSize / 2.0) - (poptipSize / 2.0);
  285. }
  286. #endregion
  287. }
  288. }