[WPF] How to develop and editable Textblock ?
Here is another request that a friend of mine asked me recently. To achieve this, I’ve just create a custom control that contains a TextBlock and a TextBox (which is hidden) controls.
When user double clic on the TextBlock, the Textbox appears.
So here is my proposition: in the file generic.xaml, put this:
<Style TargetType="{x:Type local:EditableTextBlock}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:EditableTextBlock}">
<Grid x:Name="PART_GridContainer"
Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<TextBlock x:Name="PART_TbDisplayText"
Visibility="Visible"
Background="{Binding Mode=TwoWay, Path=TextBlockBackgroundColor, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}"
Foreground="{Binding Mode=TwoWay, Path=TextBlockForegroundColor, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}"
Text="{Binding Mode=TwoWay, Path=Text, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}" />
<TextBox x:Name="PART_TbEditText"
Visibility="Hidden"
Background="{Binding Mode=TwoWay, Path=TextBoxBackgroundColor, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}"
Foreground="{Binding Mode=TwoWay, Path=TextBoxForegroundColor, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}"
Text="{Binding Mode=TwoWay, Path=Text, RelativeSource={RelativeSource AncestorType={x:Type local:EditableTextBlock}}}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then, here is the content that should go in the behind file:
[TemplatePart(Type = typeof(Grid), Name = EditableTextBlock.GRID_NAME)]
[TemplatePart(Type = typeof(TextBlock), Name = EditableTextBlock.TEXTBLOCK_DISPLAYTEXT_NAME)]
[TemplatePart(Type = typeof(TextBox), Name = EditableTextBlock.TEXTBOX_EDITTEXT_NAME)]
public class EditableTextBlock : Control
{
#region Constants
private const string GRID_NAME = "PART_GridContainer";
private const string TEXTBLOCK_DISPLAYTEXT_NAME = "PART_TbDisplayText";
private const string TEXTBOX_EDITTEXT_NAME = "PART_TbEditText";
#endregion
#region Member Fields
private Grid m_GridContainer;
private TextBlock m_TextBlockDisplayText;
private TextBox m_TextBoxEditText;
#endregion
#region Dependency Properties
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(EditableTextBlock), new UIPropertyMetadata(string.Empty));
public Brush TextBlockForegroundColor
{
get { return (Brush)GetValue(TextBlockForegroundColorProperty); }
set { SetValue(TextBlockForegroundColorProperty, value); }
}
public static readonly DependencyProperty TextBlockForegroundColorProperty = DependencyProperty.Register("TextBlockForegroundColor", typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(null));
public Brush TextBlockBackgroundColor
{
get { return (Brush)GetValue(TextBlockBackgroundColorProperty); }
set { SetValue(TextBlockBackgroundColorProperty, value); }
}
public static readonly DependencyProperty TextBlockBackgroundColorProperty = DependencyProperty.Register("TextBlockBackgroundColor", typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(null));
public Brush TextBoxForegroundColor
{
get { return (Brush)GetValue(TextBoxForegroundColorProperty); }
set { SetValue(TextBoxForegroundColorProperty, value); }
}
public static readonly DependencyProperty TextBoxForegroundColorProperty = DependencyProperty.Register("TextBoxForegroundColor", typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(null));
public Brush TextBoxBackgroundColor
{
get { return (Brush)GetValue(TextBoxBackgroundColorProperty); }
set { SetValue(TextBoxBackgroundColorProperty, value); }
}
public static readonly DependencyProperty TextBoxBackgroundColorProperty = DependencyProperty.Register("TextBoxBackgroundColor", typeof(Brush), typeof(EditableTextBlock), new UIPropertyMetadata(null));
#endregion
#region Constructor
static EditableTextBlock()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(EditableTextBlock), new FrameworkPropertyMetadata(typeof(EditableTextBlock)));
}
#endregion
#region Overrides Methods
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.m_GridContainer = this.Template.FindName(GRID_NAME, this) as Grid;
if(this.m_GridContainer != null)
{
this.m_TextBlockDisplayText = this.m_GridContainer.Children[0] as TextBlock;
this.m_TextBoxEditText = this.m_GridContainer.Children[1] as TextBox;
this.m_TextBoxEditText.LostFocus += this.OnTextBoxLostFocus;
}
}
protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
{
base.OnMouseDoubleClick(e);
this.m_TextBlockDisplayText.Visibility = Visibility.Hidden;
this.m_TextBoxEditText.Visibility = Visibility.Visible;
}
#endregion
#region Event Handlers
private void OnTextBoxLostFocus(object sender, RoutedEventArgs e)
{
this.m_TextBlockDisplayText.Visibility = Visibility.Visible;
this.m_TextBoxEditText.Visibility = Visibility.Hidden;
}
#endregion
}
As you can see, it’s pretty simple but very useful :)
Happy coding !
Bye.