LoginSignup
0
1

【WPF】編集可能なTextBlockを作成:EditableTextBlock

Posted at

概要

編集可能なTextBlockを作成する。
TextBlockを直接編集可能にするわけではなく、通常時はTextBlockでダブルクリックをするとTextBoxになるコントロールを作成します。
編集中にEnterを入力すると編集が完了し、TextBlockに戻ります。Escapeを入力すると元のテキストに戻ります。
image.png

プロジェクトの作成

下記画像のように、プロジェクトを作成し、プロジェクト配下にEditableTextBlock.csを追加しました。

プロジェクトテンプレート
WPF アプリケーション
プロジェクト名
EditableTextBlockProject

image.png

EditablTextBlock.cs

ContentControlを継承したクラスを作成し、Grid、TextBlock、TextBoxを配置したシンプルなコントロールです。

EditableTextBlock.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;

namespace EditableTextBlockProject;

public class EditableTextBlock : ContentControl
{
    private readonly Grid grid = new();
    private readonly TextBox textBox = new();
    private readonly TextBlock textBlock = new();
    private string previewText = string.Empty;
    private bool isEditMode = false;

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
            nameof(Text),
            typeof(string),
            typeof(EditableTextBlock),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

            
    public EditableTextBlock()
    {
        InitializeControl();

        MouseDoubleClick += EditableTextBlock_MouseDoubleClick;
        textBox.KeyDown += TextBox_KeyDown;
        textBox.LostFocus += TextBox_LostFocus;
    }

    
    private void InitializeControl()
    {
        textBox.Padding = new Thickness(1.0);
        textBox.Visibility = Visibility.Hidden;
        textBox.VerticalAlignment = VerticalAlignment.Center;
        textBox.VerticalContentAlignment = VerticalAlignment.Center;

        textBlock.Visibility = Visibility.Visible;
        textBlock.VerticalAlignment = VerticalAlignment.Center;

        grid.Children.Add(textBlock);
        grid.Children.Add(textBox);
        Content = grid;
        Focusable = false;
        grid.Focusable = false;
        textBlock.Focusable = false;
        MinWidth = 10;

        Binding binding = new(nameof(Text))
        {
            Source = this,
            UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
        };
        textBox.SetBinding(TextBox.TextProperty, binding);
        textBlock.SetBinding(TextBlock.TextProperty, binding);
    }

    private void EditableTextBlock_MouseDoubleClick(object sender, MouseEventArgs e)
    {
        if (!isEditMode)
        {
            previewText = textBlock.Text;
            isEditMode = true;
            OnIsEditModeChanged(isEditMode);
            textBox.Focus();
            textBox.SelectAll();
            e.Handled = true;
        }
    }

    private void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            isEditMode = false;
            OnIsEditModeChanged(isEditMode);
            e.Handled = true;
        }
        else if (e.Key == Key.Escape)
        {
            textBox.Text = previewText;
            isEditMode = false;
            OnIsEditModeChanged(isEditMode);
            e.Handled = true;
        }
    }

    private void TextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        isEditMode = false;
        OnIsEditModeChanged(isEditMode);
        e.Handled = true;
    }

    private void OnIsEditModeChanged(bool value)
    {
        textBlock.Visibility = value ? Visibility.Hidden : Visibility.Visible;
        textBox.Visibility = value ? Visibility.Visible : Visibility.Hidden;
    }
}

MainWindow

利用側のコード

MainWindow.xaml
<Window
    x:Class="EditableTextBlockProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:EditableTextBlockProject"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <local:EditableTextBlock Text="Sample Text" Margin="10"/>
    </StackPanel>
</Window>

まとめ

編集可能なテキストブロックを作成しました。
趣味でプログラミングをしている初心者が作成したコードのため、問題があればご指摘いただけると助かります。
自由に改変したり、公開してもOKですが、本コードを利用して発生した問題について責任を追うことができませんのでご注意ください。

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1