DraggableWindow.cs
上传用户:huazai0421
上传日期:2008-05-30
资源大小:405k
文件大小:13k
源码类别:

SilverLight

开发平台:

C#

  1. using System.Windows;
  2. using System.Windows.Controls;
  3. using System.Windows.Input;
  4. using System.Windows.Markup;
  5. using System.Windows.Media;
  6. namespace ESRI.ArcGIS.Samples
  7. {
  8. /// <summary>
  9. /// Resizable and draggable custom window control
  10. /// </summary>
  11. [TemplatePart(Name = "btnClose", Type = typeof(Button))] //Close button
  12. [TemplatePart(Name = "TopBar", Type = typeof(UIElement))] //top bar / area used for dragging the window
  13. [TemplatePart(Name = "ResizeWidth", Type = typeof(UIElement))] //top bar / area used for dragging the window
  14. [TemplatePart(Name = "ResizeHeight", Type = typeof(UIElement))] //top bar / area used for dragging the window
  15. [TemplateVisualState(GroupName = "CommonStates", Name = "Normal")]
  16. [TemplateVisualState(GroupName = "CommonStates", Name = "MouseOver")]
  17. [TemplateVisualState(GroupName = "CommonStates", Name = "Dragging")]
  18. [TemplateVisualState(GroupName = "CommonStates", Name = "Focus")]
  19. [ContentProperty("Content")]
  20. public class DraggableWindow : ContentControl
  21. {
  22. UIElement topbar;
  23. UIElement ResizeWidth;
  24. UIElement ResizeHeight;
  25. Point lastPoint;
  26. bool isMouseOver = false;
  27. bool isDragging = false;
  28. bool hasFocus = false;
  29. public DraggableWindow()
  30. {
  31. DefaultStyleKey = typeof(DraggableWindow);
  32. this.MouseEnter += (s, e) => { this.isMouseOver = true; ChangeVisualState(true); };
  33. this.MouseLeave += (s, e) => { this.isMouseOver = false; ChangeVisualState(true); };
  34. this.GotFocus += (s, e) => { this.hasFocus = true; ChangeVisualState(true); };
  35. this.LostFocus += (s, e) => { this.hasFocus = false; ChangeVisualState(true); };
  36. }
  37. /// <summary>
  38. /// When overridden in a derived class, is invoked whenever application code or
  39. /// internal processes (such as a rebuilding layout pass) call
  40. /// <see cref="M:System.Windows.Controls.Control.ApplyTemplate"/>.
  41. /// </summary>
  42. public override void OnApplyTemplate()
  43. {
  44. base.OnApplyTemplate();
  45. Button btnClose = GetTemplateChild("btnClose") as Button;
  46. if (btnClose != null)
  47. {
  48. btnClose.Click += (s, e) => { this.IsOpen = false; };
  49. }
  50. topbar = GetTemplateChild("TopBar") as UIElement;
  51. if (topbar != null)
  52. {
  53. topbar.MouseLeftButtonDown += topbar_MouseLeftButtonDown;
  54. }
  55. this.RenderTransform = new TranslateTransform();
  56. ResizeWidth = GetTemplateChild("ResizeWidth") as UIElement;
  57. ResizeHeight = GetTemplateChild("ResizeHeight") as UIElement;
  58. if (ResizeWidth != null)
  59. {
  60. ResizeWidth.MouseLeftButtonDown += Resize_MouseLeftButtonDown;
  61. ResizeWidth.IsHitTestVisible = IsWidthResizeable;
  62. }
  63. if (ResizeHeight != null)
  64. {
  65. ResizeHeight.MouseLeftButtonDown += Resize_MouseLeftButtonDown;
  66. ResizeHeight.IsHitTestVisible = IsHeightResizeable;
  67. }
  68. ChangeVisualState(false);
  69. }
  70. bool resizingWidth;
  71. private void Resize_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  72. {
  73. resizingWidth = (sender == ResizeWidth);
  74. if (resizingWidth && double.IsNaN(this.Width))
  75. return; //not supported/disabled
  76. else if (!resizingWidth && double.IsNaN(this.Height))
  77. return; //not supported/disabled
  78. lastPoint = e.GetPosition(this.Parent as UIElement);
  79. Application.Current.RootVisual.MouseMove += Resize_MouseMove;
  80. Application.Current.RootVisual.MouseLeftButtonUp += Resize_MouseLeftButtonUp;
  81. Application.Current.RootVisual.MouseLeave += Resize_MouseLeave;
  82. e.Handled = true;
  83. }
  84. private void Resize_MouseMove(object sender, MouseEventArgs e)
  85. {
  86. Point p2 = e.GetPosition(this.Parent as UIElement);
  87. if (resizingWidth)
  88. {
  89. double d =  p2.X - lastPoint.X;
  90. this.Width += d;
  91. if (this.HorizontalAlignment == HorizontalAlignment.Center)
  92. this.HorizontalOffset += d / 2; 
  93. else if (this.HorizontalAlignment == HorizontalAlignment.Right)
  94.     this.HorizontalOffset += d;
  95. }
  96. else
  97. {
  98. double d = p2.Y - lastPoint.Y;
  99. this.Height += d;
  100. if(this.VerticalAlignment ==  VerticalAlignment.Bottom)
  101. this.VerticalOffset += d;
  102. else if (this.VerticalAlignment == VerticalAlignment.Center)
  103. this.VerticalOffset += d / 2; 
  104. }
  105. lastPoint = p2;
  106. }
  107. private void Resize_MouseLeave(object sender, MouseEventArgs e)
  108. {
  109. StopResize();
  110. }
  111. private void Resize_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  112. {
  113. StopResize();
  114. }
  115. private void StopResize()
  116. {
  117. Application.Current.RootVisual.MouseMove -= Resize_MouseMove;
  118. Application.Current.RootVisual.MouseLeftButtonUp -= Resize_MouseLeftButtonUp;
  119. Application.Current.RootVisual.MouseLeave -= Resize_MouseLeave;
  120. }
  121. /// <summary>
  122. /// Starts tragging window drag
  123. /// </summary>
  124. /// <param name="sender">The source of the event.</param>
  125. /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
  126. private void topbar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  127. {
  128. if (!IsDraggable) return;
  129. lastPoint = e.GetPosition(this.Parent as UIElement);
  130. Application.Current.RootVisual.MouseMove += RootVisual_MouseMove;
  131. Application.Current.RootVisual.MouseLeftButtonUp += RootVisual_MouseLeftButtonUp;
  132. Application.Current.RootVisual.MouseLeave += RootVisual_MouseLeave;
  133. e.Handled = true;
  134. }
  135. private void RootVisual_MouseLeave(object sender, MouseEventArgs e)
  136. {
  137. StopDrag();
  138. }
  139. private void RootVisual_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  140. {
  141. StopDrag();
  142. }
  143. /// <summary>
  144. /// Stops tracking window drag.
  145. /// </summary>
  146. private void StopDrag()
  147. {
  148. isDragging = false;
  149. Application.Current.RootVisual.MouseMove -= RootVisual_MouseMove;
  150. Application.Current.RootVisual.MouseLeftButtonUp -= RootVisual_MouseLeftButtonUp;
  151. Application.Current.RootVisual.MouseLeave -= RootVisual_MouseLeave;
  152. ChangeVisualState(true);
  153. }
  154. private void RootVisual_MouseMove(object sender, MouseEventArgs e)
  155. {
  156. isDragging = true;
  157. ChangeVisualState(true);
  158. TranslateTransform t = this.RenderTransform as TranslateTransform;
  159. Point p2 = e.GetPosition(this.Parent as UIElement);
  160. double dX = p2.X - lastPoint.X;
  161. double dY = p2.Y - lastPoint.Y;
  162. HorizontalOffset += dX;
  163. VerticalOffset += dY;
  164. lastPoint = p2;
  165. }
  166. private void ChangeVisualState(bool useTransitions)
  167. {
  168. if (isDragging)
  169. {
  170. GoToState(useTransitions, "Dragging");
  171. }
  172. else if (hasFocus)
  173. {
  174. GoToState(useTransitions, "Focus");
  175. }
  176. else if (isMouseOver)
  177. {
  178. GoToState(useTransitions, "MouseOver");
  179. }
  180. else
  181. {
  182. GoToState(useTransitions, "Normal");
  183. }
  184. }
  185. private bool GoToState(bool useTransitions, string stateName)
  186. {
  187. return VisualStateManager.GoToState(this, stateName, useTransitions);
  188. }
  189. #region Dependency Properties
  190. /// <summary>
  191. /// Identifies the <see cref="Title"/> dependency property.
  192. /// </summary>
  193. public static readonly DependencyProperty TitleProperty =
  194. DependencyProperty.Register("Title", typeof(string), typeof(DraggableWindow), null);
  195. /// <summary>
  196. /// Gets or sets Title.
  197. /// </summary>
  198. public string Title
  199. {
  200. get { return (string)GetValue(TitleProperty); }
  201. set { SetValue(TitleProperty, value); }
  202. }
  203. /// <summary>
  204. /// Identifies the <see cref="IsOpen"/> dependency property.
  205. /// </summary>
  206. public static readonly DependencyProperty IsOpenProperty =
  207. DependencyProperty.Register("IsOpen", typeof(bool), typeof(DraggableWindow),
  208. new PropertyMetadata(true, OnIsOpenPropertyChanged));
  209. /// <summary>
  210. /// Gets or sets IsOpen.
  211. /// </summary>
  212. public bool IsOpen
  213. {
  214. get { return (bool)GetValue(IsOpenProperty); }
  215. set { SetValue(IsOpenProperty, value); }
  216. }
  217. /// <summary>
  218. /// IsOpenProperty property changed handler. 
  219. /// </summary>
  220. /// <param name="d">Window that changed its IsOpen.</param>
  221. /// <param name="e">DependencyPropertyChangedEventArgs.</param> 
  222. private static void OnIsOpenPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  223. {
  224. DraggableWindow dp = d as DraggableWindow;
  225. bool isOpen = (bool)e.NewValue;
  226. dp.Visibility = isOpen ? Visibility.Visible : Visibility.Collapsed;
  227. if (isOpen)
  228. dp.OnOpened();
  229. else
  230. dp.OnClosed();
  231. }
  232. /// <summary>
  233. /// Identifies the <see cref="HorizontalOffset"/> dependency property.
  234. /// </summary>
  235. public static readonly DependencyProperty HorizontalOffsetProperty =
  236. DependencyProperty.Register("HorizontalOffset", typeof(double), typeof(DraggableWindow),
  237. new PropertyMetadata(0.0, OnHorizontalOffsetPropertyChanged));
  238. /// <summary>
  239. /// Gets or sets HorisontalOffset.
  240. /// </summary>
  241. public double HorizontalOffset
  242. {
  243. get { return (double)GetValue(HorizontalOffsetProperty); }
  244. set { SetValue(HorizontalOffsetProperty, value); }
  245. }
  246. /// <summary>
  247. /// HorisontalOffsetProperty property changed handler. 
  248. /// </summary>
  249. /// <param name="d">Window that changed its HorisontalOffset.</param>
  250. /// <param name="e">DependencyPropertyChangedEventArgs.</param> 
  251. private static void OnHorizontalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  252. {
  253. DraggableWindow dp = d as DraggableWindow;
  254. if (dp.RenderTransform is TranslateTransform)
  255. (dp.RenderTransform as TranslateTransform).X = (double)e.NewValue;
  256. }
  257. /// <summary>
  258. /// Identifies the <see cref="VerticalOffset"/> dependency property.
  259. /// </summary>
  260. public static readonly DependencyProperty VerticalOffsetProperty =
  261. DependencyProperty.Register("VerticalOffset", typeof(double), typeof(DraggableWindow),
  262. new PropertyMetadata(0.0, OnVerticalOffsetPropertyChanged));
  263. /// <summary>
  264. /// Gets or sets VerticalOffset.
  265. /// </summary>
  266. public double VerticalOffset
  267. {
  268. get { return (double)GetValue(VerticalOffsetProperty); }
  269. set { SetValue(VerticalOffsetProperty, value); }
  270. }
  271. /// <summary>
  272. /// VerticalOffsetProperty property changed handler. 
  273. /// </summary>
  274. /// <param name="d">Window that changed its VerticalOffset.</param>
  275. /// <param name="e">DependencyPropertyChangedEventArgs.</param> 
  276. private static void OnVerticalOffsetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  277. {
  278. DraggableWindow dp = d as DraggableWindow;
  279. if (dp.RenderTransform is TranslateTransform)
  280. (dp.RenderTransform as TranslateTransform).Y = (double)e.NewValue;
  281. }
  282. /// <summary>
  283. /// Identifies the <see cref="IsDraggable"/> dependency property.
  284. /// </summary>
  285. public static readonly DependencyProperty IsDraggableProperty =
  286. DependencyProperty.Register("IsDraggable", typeof(bool), typeof(DraggableWindow),
  287. new PropertyMetadata(true));
  288. /// <summary>
  289. /// Gets or sets IsDraggable.
  290. /// </summary>
  291. public bool IsDraggable
  292. {
  293. get { return (bool)GetValue(IsDraggableProperty); }
  294. set { SetValue(IsDraggableProperty, value); }
  295. }
  296. /// <summary>
  297. /// Identifies the <see cref="IsWidthResizeable"/> dependency property.
  298. /// </summary>
  299. public static readonly DependencyProperty IsWidthResizeableProperty =
  300. DependencyProperty.Register("IsWidthResizeable", typeof(bool), typeof(DraggableWindow),
  301. new PropertyMetadata(true));
  302. /// <summary>
  303. /// Gets or sets IsWidthResizeable.
  304. /// </summary>
  305. public bool IsWidthResizeable
  306. {
  307. get { return (bool)GetValue(IsWidthResizeableProperty); }
  308. set { SetValue(IsWidthResizeableProperty, value); }
  309. }
  310. /// <summary>
  311. /// IsWidthResizeableProperty property changed handler. 
  312. /// </summary>
  313. /// <param name="d">Window that changed its IsWidthResizeable.</param>
  314. /// <param name="e">DependencyPropertyChangedEventArgs.</param> 
  315. private static void OnIsWidthResizeablePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  316. {
  317. DraggableWindow dp = d as DraggableWindow;
  318. if (dp.ResizeWidth != null)
  319. {
  320. dp.ResizeWidth.IsHitTestVisible = (bool)e.NewValue;
  321. }
  322. }
  323. /// <summary>
  324. /// Identifies the <see cref="IsHeightResizeable"/> dependency property.
  325. /// </summary>
  326. public static readonly DependencyProperty IsHeightResizeableProperty =
  327. DependencyProperty.Register("IsHeightResizeable", typeof(bool), typeof(DraggableWindow),
  328. new PropertyMetadata(true, OnIsHeightResizeablePropertyChanged));
  329. /// <summary>
  330. /// Gets or sets IsHeightResizeable.
  331. /// </summary>
  332. public bool IsHeightResizeable
  333. {
  334. get { return (bool)GetValue(IsHeightResizeableProperty); }
  335. set { SetValue(IsHeightResizeableProperty, value); }
  336. }
  337. /// <summary>
  338. /// IsHeightResizeableProperty property changed handler. 
  339. /// </summary>
  340. /// <param name="d">Window that changed its VerticalOffset.</param>
  341. /// <param name="e">DependencyPropertyChangedEventArgs.</param> 
  342. private static void OnIsHeightResizeablePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  343. {
  344. DraggableWindow dp = d as DraggableWindow;
  345. if (dp.ResizeHeight != null)
  346. {
  347. dp.ResizeHeight.IsHitTestVisible = (bool)e.NewValue;
  348. }
  349. }
  350. #endregion
  351. #region Events
  352. public event System.EventHandler Closed;
  353. public event System.EventHandler Opened;
  354. protected void OnClosed()
  355. {
  356. if(Closed!=null)
  357. {
  358. Closed(this, new System.EventArgs());
  359. }
  360. }
  361. protected void OnOpened()
  362. {
  363. if (Opened != null)
  364. {
  365. Opened(this, new System.EventArgs());
  366. }
  367. }
  368. #endregion
  369. }
  370. }