AvalonEditを使ってみた
AvalonEditとは
.net環境で使える超高機能なテキストエディタのライブラリです。
シンタックスハイライトや、複数行の折り畳み機能、コード補間などの機能をもったエディタをお手軽に作ることができます。
C#でVisualStudio的なIDEを作っているSharpDevelopというOSSプロジェクトがあるのですが、このIDEでテキストエディタ部分に使われているのがAvalonEditというライブラリです。
http://www.icsharpcode.net/OpenSource/SD/
参考リンク
- 公式ページのドキュメント
- http://avalonedit.net/documentation/
- 細かいこと調べるときはここを参照
- CodeProjectの解説ページ
- http://www.codeproject.com/Articles/42490/Using-AvalonEdit-WPF-Text-Editor
- いろいろな使い方やクラス構成の説明など。
- GitHubのサンプルコード
- https://github.com/icsharpcode/AvalonEdit/tree/master/ICSharpCode.AvalonEdit.Sample
- AvalonEditのリポジトリのサンプルコード。こいつを動かしてみると、各クラスにどんなプロパティがあるのかざっと確認できます。
使ってみる
準備
まずは、nugetからライブラリをインストールします。 NugetのGUIで「AvalonEdit」で検索するか、以下のPMコンソールから以下のコマンドでインストールします。
Install-Package AvalonEdit
エディタを表示してみる
テキストエディタのコントロールを表示するだけならメッチャ簡単。 名前空間の設定をして、↓のようにコントロールを配置するだけでOK。
<Window x:Class="AvalonEditTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:AvalonEditTest" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="MainWindow" Width="525" Height="350" mc:Ignorable="d"> <Grid> <avalonEdit:TextEditor x:Name="textEditor" Margin="10" FontFamily="Consolas" FontSize="10pt" SyntaxHighlighting="C#"/> </Grid> </Window>
よく使いそうなプロパティなど
この辺のプロパティが頻繁に使うことになりそう
プロパティ名 | 概要 |
---|---|
SyntaxHighlighting | シンタックスハイライトの言語指定を行う。C#、JavaScriptなどの文字列で指定する |
ShowLineNumbers | 行番号の表示/非表示を設定する |
HorizontalScrollBarVisibility | 水平方向のスクロールバーの表示有無などを設定 |
VerticalScrollBarVisibility | 垂直方向のスクロールバーの表示有無などを設定 |
Options | 細かいオプションを指定するためのプロパティ。TextEditorOptions型で指定する。 |
エディタのテキストを取得する
TextEditorコントロールに表示しているテキストは、Textプロパティで取得/設定できます。
ただし、このTextプロパティはDependencyPropertyではなく通常のプロパティとなっています。
そのため、WPF標準のTextBoxコントロールなどのように、Textプロパティに対してデータバインディングをすることはできません。
とりあえず、コードビハインドからテキストを取得/設定してみるサンプル
MainWindow.xaml
<Window x:Class="AvalonEditTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:AvalonEditTest" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="MainWindow" Width="525" Height="350" mc:Ignorable="d"> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <avalonEdit:TextEditor x:Name="textEditor" Margin="10" FontFamily="Consolas" FontSize="10pt" ShowLineNumbers="True" SyntaxHighlighting="C#" /> <StackPanel Grid.Row="1" Orientation="Horizontal"> <Button Grid.Row="1" Width="75" Height="20" Margin="5" Click="GetText" Content="GetText" /> <Button Grid.Row="1" Width="75" Height="20" Margin="5" Click="SetText" Content="SetText" /> </StackPanel> </Grid> </Window>
MainWindow.xaml.cs
/// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void GetText(object sender, RoutedEventArgs e) { MessageBox.Show(this.textEditor.Text); } private void SetText(object sender, RoutedEventArgs e) { this.textEditor.Text = "テキストを設定してみる。"; } }
もっと詳細なエディタの情報を取得する
エディタで扱っているテキストをもっと詳細に扱いたい場合には、Documentプロパティを使います。
このプロパティでは、現在のドキュメントの状態をTextDocument型で取得できます。
こいつはDependencyPropertyになってるんで、VM側にTextDocument型のプロパティを作っておけば、バインドして使うことができます。
VMにTextDocument型のプロパティを作って、いろいろバインドしてみました。
MainWindow.xaml
<Window x:Class="AvalonEditTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:AvalonEditTest" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="MainWindow" Width="525" Height="350" mc:Ignorable="d"> <Window.DataContext> <local:MainWindowViewModel /> </Window.DataContext> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto" /> <RowDefinition Height="100" /> </Grid.RowDefinitions> <avalonEdit:TextEditor x:Name="textEditor" Margin="10" Document="{Binding Document}" FontFamily="Consolas" FontSize="10pt" ShowLineNumbers="True" SyntaxHighlighting="C#" /> <StackPanel Grid.Row="1" Orientation="Horizontal"> <TextBlock Margin="5" Text="{Binding Document.TextLength, StringFormat=文字数:\{0:D\}}" /> <TextBlock Margin="5" Text="{Binding Document.LineCount, StringFormat=行数:\{0:D\}}" /> </StackPanel> <TextBox Grid.Row="2" Margin="5" IsReadOnly="True" Text="{Binding Document.Text}" /> </Grid> </Window>
MainWindowViewModel.cs
class MainWindowViewModel : BindableBase { private TextDocument document = new TextDocument(); public TextDocument Document { get { return document; } set { this.SetProperty(ref this.document, value); } } }
ファイルの読み書き
このTextEditorコントロールには、指定したファイルを読み込むためのLoadメソッドが用意されています。
同様にSaveメソッドでファイルへの書き込みができます。
また、ファイルを読み込んでから、エディタ上のテキストが変更されているかどうかの状態を、TextEditorのIsModifiedプロパティで取得することができます。
以下のサンプルでは、Loadボタンで指定のファイルを読み込みます。
そして、テキストになんらかの編集を加えると、IsModifiedフラグがtrueになり「編集済み」という文字が表示ます。
そしてSaveボタンでファイルを保存するとIsModifiedフラグがクリアされ、「編集済み」という表示がまた消えることが確認できます。
MainWindow.xaml
<Window x:Class="AvalonEditTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:AvalonEditTest" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="MainWindow" Width="525" Height="350" mc:Ignorable="d"> <Window.Resources> <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <avalonEdit:TextEditor x:Name="textEditor" Margin="10" Document="{Binding Document}" FontFamily="Consolas" FontSize="10pt" HorizontalScrollBarVisibility="Auto" ShowLineNumbers="True" SyntaxHighlighting="C#" VerticalScrollBarVisibility="Auto" /> <StackPanel Grid.Row="1" Orientation="Horizontal"> <Button Grid.Row="1" Width="75" Height="20" Margin="5" Click="OnLoad" Content="Load" /> <Button Grid.Row="1" Width="75" Height="20" Margin="5" Click="OnSave" Content="Save" /> <TextBlock Text="編集済み" Visibility="{Binding IsModified, ElementName=textEditor, Converter={StaticResource BooleanToVisibilityConverter}}" /> </StackPanel> </Grid> </Window>
MainWindow.xaml.cs
/// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void OnLoad(object sender, RoutedEventArgs e) { this.textEditor.Load(@"Sample.cs"); } private void OnSave(object sender, RoutedEventArgs e) { this.textEditor.Save(@"Sample.cs"); } }