using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; namespace GeekDesk.EditTextBlock { public class EditableTextBlock : TextBlock { public bool IsInEditMode { get { return (bool)GetValue(IsInEditModeProperty); } set { SetValue(IsInEditModeProperty, value); } } private EditableTextBlockAdorner _adorner; // Using a DependencyProperty as the backing store for IsInEditMode. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsInEditModeProperty = DependencyProperty.Register("IsInEditMode", typeof(bool), typeof(EditableTextBlock), new UIPropertyMetadata(false, IsInEditModeUpdate)); /// /// Determines whether [is in edit mode update] [the specified obj]. /// /// The obj. /// The instance containing the event data. private static void IsInEditModeUpdate(DependencyObject obj, DependencyPropertyChangedEventArgs e) { EditableTextBlock textBlock = obj as EditableTextBlock; if (null != textBlock) { //Get the adorner layer of the uielement (here TextBlock) AdornerLayer layer = AdornerLayer.GetAdornerLayer(textBlock); //If the IsInEditMode set to true means the user has enabled the edit mode then //add the adorner to the adorner layer of the TextBlock. if (textBlock.IsInEditMode) { if (null == textBlock._adorner) { textBlock._adorner = new EditableTextBlockAdorner(textBlock); //Events wired to exit edit mode when the user presses Enter key or leaves the control. textBlock._adorner.TextBoxKeyUp += textBlock.TextBoxKeyUp; textBlock._adorner.TextBoxLostFocus += textBlock.TextBoxLostFocus; } layer.Add(textBlock._adorner); } else { //Remove the adorner from the adorner layer. Adorner[] adorners = layer.GetAdorners(textBlock); if (adorners != null) { foreach (Adorner adorner in adorners) { if (adorner is EditableTextBlockAdorner) { layer.Remove(adorner); } } } //Update the textblock's text binding. BindingExpression expression = textBlock.GetBindingExpression(TextProperty); if (null != expression) { expression.UpdateTarget(); } } } } /// /// Gets or sets the length of the max. /// /// The length of the max. public int MaxLength { get { return (int)GetValue(MaxLengthProperty); } set { SetValue(MaxLengthProperty, value); } } // Using a DependencyProperty as the backing store for MaxLength. This enables animation, styling, binding, etc... public static readonly DependencyProperty MaxLengthProperty = DependencyProperty.Register("MaxLength", typeof(int), typeof(EditableTextBlock), new UIPropertyMetadata(0)); private void TextBoxLostFocus(object sender, RoutedEventArgs e) { IsInEditMode = false; } /// /// release the edit mode when user presses enter. /// /// The sender. /// The instance containing the event data. private void TextBoxKeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { IsInEditMode = false; } } /// /// Invoked when an unhandled  attached event reaches an element in its route that is derived from this class. Implement this method to add class handling for this event. /// /// The that contains the event data. This event data reports details about the mouse button that was pressed and the handled state. protected override void OnMouseDown(MouseButtonEventArgs e) { if (e.MiddleButton == MouseButtonState.Pressed) { IsInEditMode = true; } else if (e.ClickCount == 2) { IsInEditMode = true; } } } }