LayoutContent.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /*************************************************************************************
  2. Extended WPF Toolkit
  3. Copyright (C) 2007-2013 Xceed Software Inc.
  4. This program is provided to you under the terms of the Microsoft Public
  5. License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
  6. For more features, controls, and fast professional support,
  7. pick up the Plus Edition at http://xceed.com/wpf_toolkit
  8. Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
  9. ***********************************************************************************/
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Windows.Markup;
  15. using System.Xml.Serialization;
  16. using System.Windows;
  17. using System.Globalization;
  18. using System.Windows.Media;
  19. using System.ComponentModel;
  20. namespace Xceed.Wpf.AvalonDock.Layout
  21. {
  22. [ContentProperty("Content")]
  23. [Serializable]
  24. public abstract class LayoutContent : LayoutElement, IXmlSerializable, ILayoutElementForFloatingWindow, IComparable<LayoutContent>, ILayoutPreviousContainer
  25. {
  26. internal LayoutContent()
  27. { }
  28. #region Title
  29. public static readonly DependencyProperty TitleProperty =
  30. DependencyProperty.Register( "Title", typeof( string ), typeof( LayoutContent ), new UIPropertyMetadata( null, OnTitlePropertyChanged, CoerceTitleValue ) );
  31. public string Title
  32. {
  33. get { return ( string )GetValue( TitleProperty ); }
  34. set { SetValue( TitleProperty, value ); }
  35. }
  36. private static object CoerceTitleValue( DependencyObject obj, object value )
  37. {
  38. var lc = ( LayoutContent )obj;
  39. if( ( ( string )value ) != lc.Title )
  40. {
  41. lc.RaisePropertyChanging( LayoutContent.TitleProperty.Name );
  42. }
  43. return value;
  44. }
  45. private static void OnTitlePropertyChanged( DependencyObject obj, DependencyPropertyChangedEventArgs args )
  46. {
  47. ( ( LayoutContent )obj ).RaisePropertyChanged( LayoutContent.TitleProperty.Name );
  48. }
  49. #endregion //Title
  50. #region Content
  51. [NonSerialized]
  52. private object _content = null;
  53. [XmlIgnore]
  54. public object Content
  55. {
  56. get { return _content; }
  57. set
  58. {
  59. if (_content != value)
  60. {
  61. RaisePropertyChanging("Content");
  62. _content = value;
  63. RaisePropertyChanged("Content");
  64. }
  65. }
  66. }
  67. #endregion
  68. #region ContentId
  69. private string _contentId = null;
  70. public string ContentId
  71. {
  72. get
  73. {
  74. if (_contentId == null)
  75. {
  76. var contentAsControl = _content as FrameworkElement;
  77. if (contentAsControl != null && !string.IsNullOrWhiteSpace(contentAsControl.Name))
  78. return contentAsControl.Name;
  79. }
  80. return _contentId;
  81. }
  82. set
  83. {
  84. if (_contentId != value)
  85. {
  86. _contentId = value;
  87. RaisePropertyChanged("ContentId");
  88. }
  89. }
  90. }
  91. #endregion
  92. #region IsSelected
  93. private bool _isSelected = false;
  94. public bool IsSelected
  95. {
  96. get { return _isSelected; }
  97. set
  98. {
  99. if (_isSelected != value)
  100. {
  101. bool oldValue = _isSelected;
  102. RaisePropertyChanging("IsSelected");
  103. _isSelected = value;
  104. var parentSelector = (Parent as ILayoutContentSelector);
  105. if (parentSelector != null)
  106. parentSelector.SelectedContentIndex = _isSelected ? parentSelector.IndexOf(this) : -1;
  107. OnIsSelectedChanged(oldValue, value);
  108. RaisePropertyChanged("IsSelected");
  109. }
  110. }
  111. }
  112. /// <summary>
  113. /// Provides derived classes an opportunity to handle changes to the IsSelected property.
  114. /// </summary>
  115. protected virtual void OnIsSelectedChanged(bool oldValue, bool newValue)
  116. {
  117. if (IsSelectedChanged != null)
  118. IsSelectedChanged(this, EventArgs.Empty);
  119. }
  120. public event EventHandler IsSelectedChanged;
  121. #endregion
  122. #region IsActive
  123. [field: NonSerialized]
  124. private bool _isActive = false;
  125. [XmlIgnore]
  126. public bool IsActive
  127. {
  128. get { return _isActive; }
  129. set
  130. {
  131. if (_isActive != value)
  132. {
  133. RaisePropertyChanging("IsActive");
  134. bool oldValue = _isActive;
  135. _isActive = value;
  136. var root = Root;
  137. if (root != null && _isActive)
  138. root.ActiveContent = this;
  139. if (_isActive)
  140. IsSelected = true;
  141. OnIsActiveChanged(oldValue, value);
  142. RaisePropertyChanged("IsActive");
  143. }
  144. }
  145. }
  146. /// <summary>
  147. /// Provides derived classes an opportunity to handle changes to the IsActive property.
  148. /// </summary>
  149. protected virtual void OnIsActiveChanged(bool oldValue, bool newValue)
  150. {
  151. if (newValue)
  152. LastActivationTimeStamp = DateTime.Now;
  153. if (IsActiveChanged != null)
  154. IsActiveChanged(this, EventArgs.Empty);
  155. }
  156. public event EventHandler IsActiveChanged;
  157. #endregion
  158. #region IsLastFocusedDocument
  159. private bool _isLastFocusedDocument = false;
  160. public bool IsLastFocusedDocument
  161. {
  162. get { return _isLastFocusedDocument; }
  163. internal set
  164. {
  165. if (_isLastFocusedDocument != value)
  166. {
  167. RaisePropertyChanging("IsLastFocusedDocument");
  168. _isLastFocusedDocument = value;
  169. RaisePropertyChanged("IsLastFocusedDocument");
  170. }
  171. }
  172. }
  173. #endregion
  174. #region PreviousContainer
  175. [field: NonSerialized]
  176. private ILayoutContainer _previousContainer = null;
  177. [XmlIgnore]
  178. ILayoutContainer ILayoutPreviousContainer.PreviousContainer
  179. {
  180. get { return _previousContainer; }
  181. set
  182. {
  183. if (_previousContainer != value)
  184. {
  185. _previousContainer = value;
  186. RaisePropertyChanged("PreviousContainer");
  187. var paneSerializable = _previousContainer as ILayoutPaneSerializable;
  188. if (paneSerializable != null &&
  189. paneSerializable.Id == null)
  190. paneSerializable.Id = Guid.NewGuid().ToString();
  191. }
  192. }
  193. }
  194. protected ILayoutContainer PreviousContainer
  195. {
  196. get { return ((ILayoutPreviousContainer)this).PreviousContainer; }
  197. set { ((ILayoutPreviousContainer)this).PreviousContainer = value; }
  198. }
  199. [XmlIgnore]
  200. string ILayoutPreviousContainer.PreviousContainerId
  201. {
  202. get;
  203. set;
  204. }
  205. protected string PreviousContainerId
  206. {
  207. get { return ((ILayoutPreviousContainer)this).PreviousContainerId; }
  208. set { ((ILayoutPreviousContainer)this).PreviousContainerId = value; }
  209. }
  210. #endregion
  211. #region PreviousContainerIndex
  212. [field: NonSerialized]
  213. private int _previousContainerIndex = -1;
  214. [XmlIgnore]
  215. public int PreviousContainerIndex
  216. {
  217. get { return _previousContainerIndex; }
  218. set
  219. {
  220. if (_previousContainerIndex != value)
  221. {
  222. _previousContainerIndex = value;
  223. RaisePropertyChanged("PreviousContainerIndex");
  224. }
  225. }
  226. }
  227. #endregion
  228. #region LastActivationTimeStamp
  229. private DateTime? _lastActivationTimeStamp = null;
  230. public DateTime? LastActivationTimeStamp
  231. {
  232. get { return _lastActivationTimeStamp; }
  233. set
  234. {
  235. if (_lastActivationTimeStamp != value)
  236. {
  237. _lastActivationTimeStamp = value;
  238. RaisePropertyChanged("LastActivationTimeStamp");
  239. }
  240. }
  241. }
  242. #endregion
  243. protected override void OnParentChanging(ILayoutContainer oldValue, ILayoutContainer newValue)
  244. {
  245. var root = Root;
  246. if (oldValue != null)
  247. IsSelected = false;
  248. //if (root != null && _isActive && newValue == null)
  249. // root.ActiveContent = null;
  250. base.OnParentChanging(oldValue, newValue);
  251. }
  252. protected override void OnParentChanged(ILayoutContainer oldValue, ILayoutContainer newValue)
  253. {
  254. if (IsSelected && Parent != null && Parent is ILayoutContentSelector)
  255. {
  256. var parentSelector = (Parent as ILayoutContentSelector);
  257. parentSelector.SelectedContentIndex = parentSelector.IndexOf(this);
  258. }
  259. //var root = Root;
  260. //if (root != null && _isActive)
  261. // root.ActiveContent = this;
  262. base.OnParentChanged(oldValue, newValue);
  263. }
  264. /// <summary>
  265. /// Test if the content can be closed
  266. /// </summary>
  267. /// <returns></returns>
  268. internal bool TestCanClose()
  269. {
  270. CancelEventArgs args = new CancelEventArgs();
  271. OnClosing(args);
  272. if (args.Cancel)
  273. return false;
  274. return true;
  275. }
  276. internal void CloseInternal()
  277. {
  278. var root = Root;
  279. var parentAsContainer = Parent as ILayoutContainer;
  280. parentAsContainer.RemoveChild( this );
  281. if( root != null )
  282. root.CollectGarbage();
  283. OnClosed();
  284. }
  285. /// <summary>
  286. /// Close the content
  287. /// </summary>
  288. /// <remarks>Please note that usually the anchorable is only hidden (not closed). By default when user click the X button it only hides the content.</remarks>
  289. public abstract void Close();
  290. /// <summary>
  291. /// Event fired when the content is closed (i.e. removed definitely from the layout)
  292. /// </summary>
  293. public event EventHandler Closed;
  294. protected virtual void OnClosed()
  295. {
  296. if (Closed != null)
  297. Closed(this, EventArgs.Empty);
  298. }
  299. /// <summary>
  300. /// Event fired when the content is about to be closed (i.e. removed definitely from the layout)
  301. /// </summary>
  302. /// <remarks>Please note that LayoutAnchorable also can be hidden. Usually user hide anchorables when click the 'X' button. To completely close
  303. /// an anchorable the user should click the 'Close' menu item from the context menu. When an LayoutAnchorable is hidden its visibility changes to false and
  304. /// IsHidden property is set to true.
  305. /// Hanlde the Hiding event for the LayoutAnchorable to cancel the hide operation.</remarks>
  306. public event EventHandler<CancelEventArgs> Closing;
  307. protected virtual void OnClosing(CancelEventArgs args)
  308. {
  309. if (Closing != null)
  310. Closing(this, args);
  311. }
  312. public System.Xml.Schema.XmlSchema GetSchema()
  313. {
  314. return null;
  315. }
  316. public virtual void ReadXml(System.Xml.XmlReader reader)
  317. {
  318. if (reader.MoveToAttribute("Title"))
  319. Title = reader.Value;
  320. //if (reader.MoveToAttribute("IconSource"))
  321. // IconSource = new Uri(reader.Value, UriKind.RelativeOrAbsolute);
  322. if (reader.MoveToAttribute("IsSelected"))
  323. IsSelected = bool.Parse(reader.Value);
  324. if (reader.MoveToAttribute("ContentId"))
  325. ContentId = reader.Value;
  326. if (reader.MoveToAttribute("IsLastFocusedDocument"))
  327. IsLastFocusedDocument = bool.Parse(reader.Value);
  328. if (reader.MoveToAttribute("PreviousContainerId"))
  329. PreviousContainerId = reader.Value;
  330. if (reader.MoveToAttribute("PreviousContainerIndex"))
  331. PreviousContainerIndex = int.Parse(reader.Value);
  332. if (reader.MoveToAttribute("FloatingLeft"))
  333. FloatingLeft = double.Parse(reader.Value, CultureInfo.InvariantCulture);
  334. if (reader.MoveToAttribute("FloatingTop"))
  335. FloatingTop = double.Parse(reader.Value, CultureInfo.InvariantCulture);
  336. if (reader.MoveToAttribute("FloatingWidth"))
  337. FloatingWidth = double.Parse(reader.Value, CultureInfo.InvariantCulture);
  338. if (reader.MoveToAttribute("FloatingHeight"))
  339. FloatingHeight = double.Parse(reader.Value, CultureInfo.InvariantCulture);
  340. if (reader.MoveToAttribute("IsMaximized"))
  341. IsMaximized = bool.Parse(reader.Value);
  342. if (reader.MoveToAttribute("CanClose"))
  343. CanClose = bool.Parse(reader.Value);
  344. if (reader.MoveToAttribute("CanFloat"))
  345. CanFloat = bool.Parse(reader.Value);
  346. if (reader.MoveToAttribute("LastActivationTimeStamp"))
  347. LastActivationTimeStamp = DateTime.Parse(reader.Value, CultureInfo.InvariantCulture);
  348. reader.Read();
  349. }
  350. public virtual void WriteXml(System.Xml.XmlWriter writer)
  351. {
  352. if (!string.IsNullOrWhiteSpace(Title))
  353. writer.WriteAttributeString("Title", Title);
  354. //if (IconSource != null)
  355. // writer.WriteAttributeString("IconSource", IconSource.ToString());
  356. if (IsSelected)
  357. writer.WriteAttributeString("IsSelected", IsSelected.ToString());
  358. if (IsLastFocusedDocument)
  359. writer.WriteAttributeString("IsLastFocusedDocument", IsLastFocusedDocument.ToString());
  360. if (!string.IsNullOrWhiteSpace(ContentId))
  361. writer.WriteAttributeString("ContentId", ContentId);
  362. if (ToolTip != null && ToolTip is string)
  363. if (!string.IsNullOrWhiteSpace((string)ToolTip))
  364. writer.WriteAttributeString("ToolTip", (string)ToolTip);
  365. if (FloatingLeft != 0.0)
  366. writer.WriteAttributeString("FloatingLeft", FloatingLeft.ToString(CultureInfo.InvariantCulture));
  367. if (FloatingTop != 0.0)
  368. writer.WriteAttributeString("FloatingTop", FloatingTop.ToString(CultureInfo.InvariantCulture));
  369. if (FloatingWidth != 0.0)
  370. writer.WriteAttributeString("FloatingWidth", FloatingWidth.ToString(CultureInfo.InvariantCulture));
  371. if (FloatingHeight != 0.0)
  372. writer.WriteAttributeString("FloatingHeight", FloatingHeight.ToString(CultureInfo.InvariantCulture));
  373. if (IsMaximized)
  374. writer.WriteAttributeString("IsMaximized", IsMaximized.ToString());
  375. if (!CanClose)
  376. writer.WriteAttributeString("CanClose", CanClose.ToString());
  377. if (!CanFloat)
  378. writer.WriteAttributeString("CanFloat", CanFloat.ToString());
  379. if (LastActivationTimeStamp != null)
  380. writer.WriteAttributeString("LastActivationTimeStamp", LastActivationTimeStamp.Value.ToString(CultureInfo.InvariantCulture));
  381. if (_previousContainer != null)
  382. {
  383. var paneSerializable = _previousContainer as ILayoutPaneSerializable;
  384. if (paneSerializable != null)
  385. {
  386. writer.WriteAttributeString("PreviousContainerId", paneSerializable.Id);
  387. writer.WriteAttributeString("PreviousContainerIndex", _previousContainerIndex.ToString());
  388. }
  389. }
  390. }
  391. #region FloatingWidth
  392. private double _floatingWidth = 0.0;
  393. public double FloatingWidth
  394. {
  395. get { return _floatingWidth; }
  396. set
  397. {
  398. if (_floatingWidth != value)
  399. {
  400. RaisePropertyChanging("FloatingWidth");
  401. _floatingWidth = value;
  402. RaisePropertyChanged("FloatingWidth");
  403. }
  404. }
  405. }
  406. #endregion
  407. #region FloatingHeight
  408. private double _floatingHeight = 0.0;
  409. public double FloatingHeight
  410. {
  411. get { return _floatingHeight; }
  412. set
  413. {
  414. if (_floatingHeight != value)
  415. {
  416. RaisePropertyChanging("FloatingHeight");
  417. _floatingHeight = value;
  418. RaisePropertyChanged("FloatingHeight");
  419. }
  420. }
  421. }
  422. #endregion
  423. #region FloatingLeft
  424. private double _floatingLeft = 0.0;
  425. public double FloatingLeft
  426. {
  427. get { return _floatingLeft; }
  428. set
  429. {
  430. if (_floatingLeft != value)
  431. {
  432. RaisePropertyChanging("FloatingLeft");
  433. _floatingLeft = value;
  434. RaisePropertyChanged("FloatingLeft");
  435. }
  436. }
  437. }
  438. #endregion
  439. #region FloatingTop
  440. private double _floatingTop = 0.0;
  441. public double FloatingTop
  442. {
  443. get { return _floatingTop; }
  444. set
  445. {
  446. if (_floatingTop != value)
  447. {
  448. RaisePropertyChanging("FloatingTop");
  449. _floatingTop = value;
  450. RaisePropertyChanged("FloatingTop");
  451. }
  452. }
  453. }
  454. #endregion
  455. #region IsMaximized
  456. private bool _isMaximized = false;
  457. public bool IsMaximized
  458. {
  459. get { return _isMaximized; }
  460. set
  461. {
  462. if (_isMaximized != value)
  463. {
  464. RaisePropertyChanging("IsMaximized");
  465. _isMaximized = value;
  466. RaisePropertyChanged("IsMaximized");
  467. }
  468. }
  469. }
  470. #endregion
  471. #region ToolTip
  472. private object _toolTip = null;
  473. public object ToolTip
  474. {
  475. get { return _toolTip; }
  476. set
  477. {
  478. if (_toolTip != value)
  479. {
  480. _toolTip = value;
  481. RaisePropertyChanged("ToolTip");
  482. }
  483. }
  484. }
  485. #endregion
  486. public bool IsFloating
  487. {
  488. get { return this.FindParent<LayoutFloatingWindow>() != null; }
  489. }
  490. #region IconSource
  491. private ImageSource _iconSource = null;
  492. public ImageSource IconSource
  493. {
  494. get { return _iconSource; }
  495. set
  496. {
  497. if (_iconSource != value)
  498. {
  499. _iconSource = value;
  500. RaisePropertyChanged("IconSource");
  501. }
  502. }
  503. }
  504. #endregion
  505. public int CompareTo(LayoutContent other)
  506. {
  507. var contentAsComparable = Content as IComparable;
  508. if (contentAsComparable != null)
  509. {
  510. return contentAsComparable.CompareTo(other.Content);
  511. }
  512. return string.Compare(Title, other.Title);
  513. }
  514. /// <summary>
  515. /// Float the content in a popup window
  516. /// </summary>
  517. public void Float()
  518. {
  519. if (PreviousContainer != null &&
  520. PreviousContainer.FindParent<LayoutFloatingWindow>() != null)
  521. {
  522. var currentContainer = Parent as ILayoutPane;
  523. var currentContainerIndex = (currentContainer as ILayoutGroup).IndexOfChild(this);
  524. var previousContainerAsLayoutGroup = PreviousContainer as ILayoutGroup;
  525. if (PreviousContainerIndex < previousContainerAsLayoutGroup.ChildrenCount)
  526. previousContainerAsLayoutGroup.InsertChildAt(PreviousContainerIndex, this);
  527. else
  528. previousContainerAsLayoutGroup.InsertChildAt(previousContainerAsLayoutGroup.ChildrenCount, this);
  529. PreviousContainer = currentContainer;
  530. PreviousContainerIndex = currentContainerIndex;
  531. IsSelected = true;
  532. IsActive = true;
  533. Root.CollectGarbage();
  534. }
  535. else
  536. {
  537. Root.Manager.StartDraggingFloatingWindowForContent(this, false);
  538. IsSelected = true;
  539. IsActive = true;
  540. }
  541. }
  542. /// <summary>
  543. /// Dock the content as document
  544. /// </summary>
  545. public void DockAsDocument()
  546. {
  547. var root = Root as LayoutRoot;
  548. if (root == null)
  549. throw new InvalidOperationException();
  550. if (Parent is LayoutDocumentPane)
  551. return;
  552. if (PreviousContainer is LayoutDocumentPane)
  553. {
  554. Dock();
  555. return;
  556. }
  557. LayoutDocumentPane newParentPane;
  558. if (root.LastFocusedDocument != null)
  559. {
  560. newParentPane = root.LastFocusedDocument.Parent as LayoutDocumentPane;
  561. }
  562. else
  563. {
  564. newParentPane = root.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
  565. }
  566. if (newParentPane != null)
  567. {
  568. newParentPane.Children.Add(this);
  569. root.CollectGarbage();
  570. }
  571. IsSelected = true;
  572. IsActive = true;
  573. }
  574. /// <summary>
  575. /// Re-dock the content to its previous container
  576. /// </summary>
  577. public void Dock()
  578. {
  579. if (PreviousContainer != null)
  580. {
  581. var currentContainer = Parent as ILayoutContainer;
  582. var currentContainerIndex = (currentContainer is ILayoutGroup) ? (currentContainer as ILayoutGroup).IndexOfChild(this) : -1;
  583. var previousContainerAsLayoutGroup = PreviousContainer as ILayoutGroup;
  584. if (PreviousContainerIndex < previousContainerAsLayoutGroup.ChildrenCount)
  585. previousContainerAsLayoutGroup.InsertChildAt(PreviousContainerIndex, this);
  586. else
  587. previousContainerAsLayoutGroup.InsertChildAt(previousContainerAsLayoutGroup.ChildrenCount, this);
  588. if (currentContainerIndex > -1)
  589. {
  590. PreviousContainer = currentContainer;
  591. PreviousContainerIndex = currentContainerIndex;
  592. }
  593. else
  594. {
  595. PreviousContainer = null;
  596. PreviousContainerIndex = 0;
  597. }
  598. IsSelected = true;
  599. IsActive = true;
  600. }
  601. else
  602. {
  603. InternalDock();
  604. }
  605. Root.CollectGarbage();
  606. }
  607. protected virtual void InternalDock()
  608. {
  609. }
  610. #region CanClose
  611. private bool _canClose = true;
  612. public bool CanClose
  613. {
  614. get { return _canClose; }
  615. set
  616. {
  617. if (_canClose != value)
  618. {
  619. _canClose = value;
  620. RaisePropertyChanged("CanClose");
  621. }
  622. }
  623. }
  624. #endregion
  625. #region CanFloat
  626. private bool _canFloat = true;
  627. public bool CanFloat
  628. {
  629. get { return _canFloat; }
  630. set
  631. {
  632. if (_canFloat != value)
  633. {
  634. _canFloat = value;
  635. RaisePropertyChanged("CanFloat");
  636. }
  637. }
  638. }
  639. #endregion
  640. }
  641. }