WPF - Editor de arquivos XAML RichTextBox (C#)


Em meu artigo - WPF - Usando o controle RichTextBox - eu apresentei o controle RichTextBox , suas propriedades , eventos e mostrei como editar, salvar e exibir o conteúdo de um RichTextBox.

Neste o objetivo é bem mais modesto, vou apenas mostrar um editor RichTextBox para editar arquivos XAML usando a linguagem C#.

Abra então o Visual C# 2010 Express Edition e crie um novo projeto (File-> New Project) usando o modelo WPF Application com o nome EditorRichText;

A seguir vamos incluir no arquivo Window1.xaml, a partir da ToolBox, os controles DockPanel, Menu, ToolBar conforme o leiaute abaixo:

 

O código XAML do arquivo pode ser visto abaixo:

itle="Editor RichTextBox Simples"
	Width="640" Height="480">
    <DockPanel>
        <Menu DockPanel.Dock="Top" Foreground="#FF3131C7">
            <MenuItem Header="Arquivo">
                <MenuItem Header="Abrir" Click="mnuFileOpen_Click"/>
                <MenuItem Header="Salvar" Click="mnuFileSave_Click"/>
            </MenuItem>
        </Menu>
        <ToolBar DockPanel.Dock="Top" Background="#F9F7E3EF">
            <ComboBox Name="cboFont" Width="140"
             SelectionChanged="cboFont_SelectionChanged">
                <ComboBoxItem Content="Times New Roman"/>
                <ComboBoxItem Content="Arial"/>
                <ComboBoxItem Content="Segoe"/>
                <ComboBoxItem Content="Comic Sans MS"/>
                <ComboBoxItem Content="Trebusch"/>
                <ComboBoxItem Content="Verdana"/>
            </ComboBox>
            <ComboBox Name="cboSize" Width="40"
             SelectionChanged="cboSize_SelectionChanged">
                <ComboBoxItem Content="8"/>
                <ComboBoxItem Content="10"/>
                <ComboBoxItem Content="12"/>
                <ComboBoxItem Content="14"/>
                <ComboBoxItem Content="16"/>
                <ComboBoxItem Content="18"/>
                <ComboBoxItem Content="24"/>
                <ComboBoxItem Content="36"/>
            </ComboBox>
            <ComboBox Name="cboColor" Width="70"
             SelectionChanged="cboColor_SelectionChanged">
                <ComboBoxItem Content="Preto"/>
                <ComboBoxItem Content="Vermelho"/>
                <ComboBoxItem Content="Verde"/>
                <ComboBoxItem Content="Azul"/>
                <ComboBoxItem Content="Cinza"/>
            </ComboBox>
            <ComboBox Name="cboWeight" Width="70"
             SelectionChanged="cboWeight_SelectionChanged">
                <ComboBoxItem Content="Normal"/>
                <ComboBoxItem Content="Negrito"/>
            </ComboBox>
            <ComboBox Name="cboStyle" Width="70"
             SelectionChanged="cboStyle_SelectionChanged">
                <ComboBoxItem Content="Normal"/>
                <ComboBoxItem Content="Italico"/>
            </ComboBox>
        </ToolBar>
        <RichTextBox SelectionChanged="rchNotes_SelectionChanged" Name="rchNotes" Grid.Row="1" SpellCheck.IsEnabled="True" Background="White">
            <FlowDocument FontFamily="Times New Roman">
                <Paragraph FontSize="18" FontWeight="Bold">
                    Exemplo XAML
                </Paragraph>
                <Paragraph FontSize="14">
                    Um editor que cria um RichTextBox quem contém um simples FlowDocument.
                </Paragraph>
            </FlowDocument>
        </RichTextBox>
    </DockPanel>
</Window>

O código code-behind correspondendo do arquivo Window1.xaml.cs é dado a seguir:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using Microsoft.Win32;
using System.Windows.Markup;
using System.IO;

namespace SimpleRichEditor
{
	public partial class Window1 : Window
	{
		public Window1()
		{
			this.InitializeComponent();
		}

        // Seleciona a fonte
        private void cboFont_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (rchNotes == null) return;
            if (e.AddedItems.Count < 1) return;
            ComboBoxItem item = (ComboBoxItem)e.AddedItems[0];
            string value = item.Content.ToString();

            FontFamily font_family = new FontFamily(value);
            rchNotes.Selection.ApplyPropertyValue(TextElement.FontFamilyProperty, font_family);
            rchNotes.Focus();
        }

        // Seleciona o tamanho da fonte
        private void cboSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (rchNotes == null) return;
            if (e.AddedItems.Count < 1) return;
            ComboBoxItem item = (ComboBoxItem)e.AddedItems[0];
            string value = item.Content.ToString();

            rchNotes.Selection.ApplyPropertyValue(TextElement.FontSizeProperty, value);
            rchNotes.Focus();
        }

        // Selecione a cor
        private void cboColor_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (rchNotes == null) return;
            if (e.AddedItems.Count < 1) return;
            ComboBoxItem item = (ComboBoxItem)e.AddedItems[0];
            string value = item.Content.ToString();

            switch (value)
            {
                case "Preto":
                    rchNotes.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
                    break;
                case "Vermelho":
                    rchNotes.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);
                    break;
                case "Verde":
                    rchNotes.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Green);
                    break;
                case "Azul":
                    rchNotes.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Blue);
                    break;
                case "Cinza":
                    rchNotes.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Gray);
                    break;
            }

            rchNotes.Focus();
        }

        // Seleciona o efeito
        private void cboWeight_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (rchNotes == null) return;
            if (e.AddedItems.Count < 1) return;
            ComboBoxItem item = (ComboBoxItem)e.AddedItems[0];
            string value = item.Content.ToString();

            switch (value)
            {
                case "Normal":
                    rchNotes.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Normal);
                    break;
                case "Negrito":
                    rchNotes.Selection.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
                    break;
            }

            rchNotes.Focus();
        }

        // define o estilo
        private void cboStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (rchNotes == null) return;
            if (e.AddedItems.Count < 1) return;
            ComboBoxItem item = (ComboBoxItem)e.AddedItems[0];
            string value = item.Content.ToString();

            switch (value)
            {
                case "Normal":
                    rchNotes.Selection.ApplyPropertyValue(TextElement.FontStyleProperty, FontStyles.Normal);
                    break;
                case "Italico":
                    rchNotes.Selection.ApplyPropertyValue(TextElement.FontStyleProperty, FontStyles.Italic);
                    break;
            }

            rchNotes.Focus();
        }

        // Exibe a seleção de propriedades
        private void rchNotes_SelectionChanged(object sender, RoutedEventArgs e)
        {
            if (rchNotes == null) return;

            // Font family.
            FontFamily font_family = rchNotes.Selection.GetPropertyValue(TextElement.FontFamilyProperty) as FontFamily;
            if (font_family == null)
            {
                cboFont.Text = "";
            } else {
                cboFont.Text = font_family.Source;
            }

            // tamanho.
            cboSize.Text = rchNotes.Selection.GetPropertyValue(TextElement.FontSizeProperty).ToString();

            // Cor.
            SolidColorBrush br = rchNotes.Selection.GetPropertyValue(TextElement.ForegroundProperty) as SolidColorBrush;
            if (br == null)
            {
                cboColor.Text = "";
            } else {
                switch (br.Color.ToString())
                {
                    case "#FF000000":
                        cboColor.Text = "Black";
                        break;
                    case "#FFFF0000":
                        cboColor.Text = "Red";
                        break;
                    case "#FF008000":
                        cboColor.Text = "Green";
                        break;
                    default:
                        cboColor.Text = "Blue";
                        break;
                }
            }

            // Fontes.
            cboWeight.Text = rchNotes.Selection.GetPropertyValue(TextElement.FontWeightProperty).ToString();

            // Estilo.
            cboStyle.Text = rchNotes.Selection.GetPropertyValue(TextElement.FontStyleProperty).ToString();
        }

        // carrega o arquivo XAML
        private void mnuFileOpen_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.DefaultExt = ".xaml";
            dlg.Filter = "XAML Files (.xaml)|*.xaml|All Files|*.*";

            if (dlg.ShowDialog() == true)
            {
                // Abre o arquivo
                XamlReader reader = new XamlReader();
                FileStream fs = File.OpenRead(dlg.FileName);
                try
                {
                    // Le o FlowDocument armazenado no arquivo
                    FlowDocument flow_document = (FlowDocument)XamlReader.Load(fs);
                    
                    // Exibe o novo FlowDocument.
                    rchNotes.Document = flow_document;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message,
                        "Erro ao ler arquivo",
                        MessageBoxButton.OK,
                        MessageBoxImage.Error);
                }
                finally
                {
                    fs.Close();
                }
            }
        }

        // Salva o documento
        private void mnuFileSave_Click(object sender, RoutedEventArgs e)
        {
            // Pega o nome do arquivo
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = ".xaml";
            dlg.Filter = "XAML Files (.xaml)|*.xaml|All Files|*.*";

            if (dlg.ShowDialog() == true)
            {
                FileStream fs = File.OpenWrite(dlg.FileName);
                try
                {
                    // Salvar
                    XamlWriter.Save(rchNotes.Document, fs);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message,
                        "Erro ao salvar o arquivo",
                        MessageBoxButton.OK,
                        MessageBoxImage.Error);
                }
                finally
                {
                    fs.Close();
                }
            }
        }
    }
}

Executando o projeto iremos obter:

Pegue o projeto completo aqui: EditorRichText.zip

Filipenses 3:20 Mas a nossa pátria está nos céus, donde também aguardamos um Salvador, o Senhor Jesus Cristo,

Referências:

José Carlos Macoratti