2 using System
.Collections
.Generic
;
4 using System
.Windows
.Controls
;
5 using System
.Windows
.Controls
.Primitives
;
6 using System
.Windows
.Input
;
8 using System
.Diagnostics
;
9 using System
.Windows
.Documents
;
10 using System
.Windows
.Media
;
15 /// EditBox is a custom cotrol that can switch between two modes:
16 /// editing and normal. When it is in editing mode, the content is
17 /// displayed in a TextBox that provides editing capbability. When
18 /// the EditBox is in normal, its content is displayed in a TextBlock
19 /// that is not editable.
21 /// This control is designed to be used in with a GridView View.
23 public class EditBox
: Control
26 #region Static Constructor
29 /// Static constructor
33 DefaultStyleKeyProperty
.OverrideMetadata(typeof(EditBox
),
34 new FrameworkPropertyMetadata(typeof(EditBox
)));
39 #region Public Methods
42 /// Called when the tree for the EditBox has been generated.
44 public override void OnApplyTemplate()
46 base.OnApplyTemplate();
47 TextBlock textBlock
= GetTemplateChild("PART_TextBlockPart")
49 Debug
.Assert(textBlock
!= null, "No TextBlock!");
51 _textBox
= new TextBox();
52 _adorner
= new EditBoxAdorner(textBlock
, _textBox
);
53 AdornerLayer layer
= AdornerLayer
.GetAdornerLayer(textBlock
);
56 _textBox
.KeyDown
+= new KeyEventHandler(OnTextBoxKeyDown
);
57 _textBox
.LostKeyboardFocus
+=
58 new KeyboardFocusChangedEventHandler(OnTextBoxLostKeyboardFocus
);
60 //Receive notification of the event to handle the column
62 HookTemplateParentResizeEvent();
64 //Capture the resize event to handle ListView resize cases.
65 HookItemsControlEvents();
67 _listViewItem
= GetDependencyObjectFromVisualTree(this,
68 typeof(ListViewItem
)) as ListViewItem
;
70 Debug
.Assert(_listViewItem
!= null, "No ListViewItem found");
75 #region Protected Methods
78 /// If the ListViewItem that contains the EditBox is selected,
79 /// when the mouse pointer moves over the EditBox, the corresponding
80 /// MouseEnter event is the first of two events (MouseUp is the second)
81 /// that allow the EditBox to change to editing mode.
83 protected override void OnMouseEnter(MouseEventArgs e
)
86 if (!IsEditing
&& IsParentSelected
)
93 /// If the MouseLeave event occurs for an EditBox control that
94 /// is in normal mode, the mode cannot be changed to editing mode
95 /// until a MouseEnter event followed by a MouseUp event occurs.
97 protected override void OnMouseLeave(MouseEventArgs e
)
100 _isMouseWithinScope
= false;
104 /// An EditBox switches to editing mode when the MouseUp event occurs
105 /// for that EditBox and the following conditions are satisfied:
106 /// 1. A MouseEnter event for the EditBox occurred before the
108 /// 2. The mouse did not leave the EditBox between the
109 /// MouseEnter and MouseUp events.
110 /// 3. The ListViewItem that contains the EditBox was selected
111 /// when the MouseEnter event occurred.
113 /// <param name="e"></param>
114 protected override void OnMouseUp(MouseButtonEventArgs e
)
118 if (e
.ChangedButton
== MouseButton
.Right
||
119 e
.ChangedButton
== MouseButton
.Middle
)
124 if (!e
.Handled
&& (_canBeEdit
|| _isMouseWithinScope
))
129 //If the first MouseUp event selects the parent ListViewItem,
130 //then the second MouseUp event puts the EditBox in editing
132 if (IsParentSelected
)
133 _isMouseWithinScope
= true;
139 #region Public Properties
144 /// ValueProperty DependencyProperty.
146 public static readonly DependencyProperty ValueProperty
=
147 DependencyProperty
.Register(
151 new FrameworkPropertyMetadata(null));
154 /// Gets or sets the value of the EditBox
158 get { return GetValue(ValueProperty); }
159 set { SetValue(ValueProperty, value); }
167 /// IsEditingProperty DependencyProperty
169 public static DependencyProperty IsEditingProperty
=
170 DependencyProperty
.Register(
174 new FrameworkPropertyMetadata(false));
177 /// Returns true if the EditBox control is in editing mode.
179 public bool IsEditing
181 get { return (bool)GetValue(IsEditingProperty); }
184 SetValue(IsEditingProperty
, value);
185 _adorner
.UpdateVisibilty(value);
191 #region IsParentSelected
194 /// Gets whether the ListViewItem that contains the
195 /// EditBox is selected.
197 private bool IsParentSelected
201 if (_listViewItem
== null)
204 return _listViewItem
.IsSelected
;
212 #region Private Methods
215 /// When an EditBox is in editing mode, pressing the ENTER or F2
216 /// keys switches the EditBox to normal mode.
218 private void OnTextBoxKeyDown(object sender
, KeyEventArgs e
)
220 if (IsEditing
&& (e
.Key
== Key
.Enter
|| e
.Key
== Key
.F2
))
228 /// If an EditBox loses focus while it is in editing mode,
229 /// the EditBox mode switches to normal mode.
231 private void OnTextBoxLostKeyboardFocus(object sender
,
232 KeyboardFocusChangedEventArgs e
)
238 /// Sets IsEditing to false when the ListViewItem that contains an
239 /// EditBox changes its size
241 private void OnCouldSwitchToNormalMode(object sender
,
248 /// Walk the visual tree to find the ItemsControl and
249 /// hook its some events on it.
251 private void HookItemsControlEvents()
253 _itemsControl
= GetDependencyObjectFromVisualTree(this,
254 typeof(ItemsControl
)) as ItemsControl
;
255 if (_itemsControl
!= null)
257 //Handle the Resize/ScrollChange/MouseWheel
258 //events to determine whether to switch to Normal mode
259 _itemsControl
.SizeChanged
+=
260 new SizeChangedEventHandler(OnCouldSwitchToNormalMode
);
261 _itemsControl
.AddHandler(ScrollViewer
.ScrollChangedEvent
,
262 new RoutedEventHandler(OnScrollViewerChanged
));
263 _itemsControl
.AddHandler(ScrollViewer
.MouseWheelEvent
,
264 new RoutedEventHandler(OnCouldSwitchToNormalMode
), true);
269 /// If an EditBox is in editing mode and the content of a ListView is
270 /// scrolled, then the EditBox switches to normal mode.
272 private void OnScrollViewerChanged(object sender
, RoutedEventArgs args
)
274 if (IsEditing
&& Mouse
.PrimaryDevice
.LeftButton
==
275 MouseButtonState
.Pressed
)
282 /// Walk visual tree to find the first DependencyObject
283 /// of the specific type.
285 private DependencyObject
286 GetDependencyObjectFromVisualTree(DependencyObject startObject
,
289 //Walk the visual tree to get the parent(ItemsControl)
291 DependencyObject parent
= startObject
;
292 while (parent
!= null)
294 if (type
.IsInstanceOfType(parent
))
297 parent
= VisualTreeHelper
.GetParent(parent
);
304 /// When the size of the column containing the EditBox changes
305 /// and the EditBox is in editing mode, switch the mode to normal mode
307 private void HookTemplateParentResizeEvent()
309 FrameworkElement parent
= TemplatedParent
as FrameworkElement
;
312 parent
.SizeChanged
+=
313 new SizeChangedEventHandler(OnCouldSwitchToNormalMode
);
319 #region private variable
321 private EditBoxAdorner _adorner
;
322 //A TextBox in the visual tree
323 private FrameworkElement _textBox
;
324 //Specifies whether an EditBox can switch to editing mode.
325 //Set to true if the ListViewItem that contains the EditBox is
326 //selected, when the mouse pointer moves over the EditBox
327 private bool _canBeEdit
;
328 //Specifies whether an EditBox can switch to editing mode.
329 //Set to true when the ListViewItem that contains the EditBox is
330 //selected when the mouse pointer moves over the EditBox.
331 private bool _isMouseWithinScope
;
332 //The ListView control that contains the EditBox
333 private ItemsControl _itemsControl
;
334 //The ListViewItem control that contains the EditBox
335 private ListViewItem _listViewItem
;