Usando um Editor de Expressões Personalizado
Um editor de expressões personalizado pode ser implementado para fornecer uma experiência de edição de expressão mais rica ou mais simples. Há vários cenários nos quais você pode querer usar um editor de expressões personalizado:
Para fornecer suporte ao IntelliSense e outros recursos avançados de edição em um designer de fluxo de trabalho rehospedado. Essa funcionalidade deve ser fornecida porque o editor de expressão padrão do Visual Studio não pode ser usado em aplicativos rehospedados.
Para simplificar a experiência de edição de expressões para os usuários analistas de negócios, para que eles não sejam, por exemplo, obrigados a aprender Visual Basic ou lidar com expressões Visual Basic.
Três etapas básicas são necessárias para implementar um editor de expressões personalizado:
Implemente a interface IExpressionEditorService. Esta interface gerencia a criação e destruição de editores de expressão.
Implemente a interface IExpressionEditorInstance. Essa interface implementa a interface do usuário para a interface do usuário de edição de expressão.
Publique o IExpressionEditorService em seu aplicativo de fluxo de trabalho rehospedado.
Implementando um Editor de Expressões Personalizado em uma Biblioteca de Classes
Aqui está um exemplo de código para uma classe (prova de conceito) MyEditorService
que implementa a IExpressionEditorService interface está contida em um projeto de biblioteca MyExpressionEditorService.
using System;
using System.Collections.Generic;
using System.Activities.Presentation.View;
using System.Activities.Presentation.Hosting;
using System.Activities.Presentation.Model;
namespace MyExpressionEditorService
{
public class MyEditorService : IExpressionEditorService
{
public void CloseExpressionEditors()
{
}
public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List<ModelItem> variables, string text)
{
MyExpressionEditorInstance instance = new MyExpressionEditorInstance();
return instance;
}
public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List<ModelItem> variables, string text, System.Windows.Size initialSize)
{
MyExpressionEditorInstance instance = new MyExpressionEditorInstance();
return instance;
}
public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List<ModelItem> variables, string text, Type expressionType)
{
MyExpressionEditorInstance instance = new MyExpressionEditorInstance();
return instance;
}
public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List<ModelItem> variables, string text, Type expressionType, System.Windows.Size initialSize)
{
MyExpressionEditorInstance instance = new MyExpressionEditorInstance();
return instance;
}
public void UpdateContext(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces)
{
}
}
}
Aqui está o código para uma MyExpressionEditorInstance
classe que implementa a IExpressionEditorInstance interface em um projeto de biblioteca MyExpressionEditorService.
using System;
using System.Activities.Presentation.View;
using System.Windows;
using System.Reflection;
using System.Windows.Controls;
namespace MyExpressionEditorService
{
public class MyExpressionEditorInstance : IExpressionEditorInstance
{
private TextBox textBox = new TextBox();
public bool AcceptsReturn { get; set; }
public bool AcceptsTab { get; set; }
public bool HasAggregateFocus {
get
{
return true;
}
}
public System.Windows.Controls.ScrollBarVisibility HorizontalScrollBarVisibility { get; set; }
public System.Windows.Controls.Control HostControl {
get
{
return textBox;
}
}
public int MaxLines { get; set; }
public int MinLines { get; set; }
public string Text { get; set; }
public System.Windows.Controls.ScrollBarVisibility VerticalScrollBarVisibility { get; set; }
public event EventHandler Closing;
public event EventHandler GotAggregateFocus;
public event EventHandler LostAggregateFocus;
public event EventHandler TextChanged;
public bool CanCompleteWord()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanCopy()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanCut()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanDecreaseFilterLevel()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanGlobalIntellisense()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanIncreaseFilterLevel()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanParameterInfo()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanPaste()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanQuickInfo()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanRedo()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool CanUndo()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public void ClearSelection()
{
MessageBox.Show(MethodBase.GetCurrentMethod().Name);
}
public void Close()
{
MessageBox.Show(MethodBase.GetCurrentMethod().Name);
}
public bool CompleteWord()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool Copy()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool Cut()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool DecreaseFilterLevel()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public void Focus()
{
MessageBox.Show(MethodBase.GetCurrentMethod().Name);
}
public string GetCommittedText()
{
return "CommittedText";
}
public bool GlobalIntellisense()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool IncreaseFilterLevel()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool ParameterInfo()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool Paste()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool QuickInfo()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool Redo()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
public bool Undo()
{
return (MessageBox.Show(MethodBase.GetCurrentMethod().Name, "TestEditorInstance", MessageBoxButton.YesNo) == MessageBoxResult.Yes);
}
}
}
Publicando um editor de expressão personalizado em um projeto WPF
Aqui está o código que mostra como rehospedar o designer em um aplicativo WPF e como criar e publicar o MyEditorService
serviço. Antes de usar esse código, adicione uma referência ao projeto de biblioteca MyExpressionEditorService do projeto que contém o aplicativo avalon2.
using System.Windows;
using System.Windows.Controls;
using System.Activities.Presentation;
using System.Activities.Statements;
using System.Activities.Core.Presentation;
using System.Activities.Presentation.View;
using MyExpressionEditorService;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private MyEditorService expressionEditorService;
public MainWindow()
{
InitializeComponent();
new DesignerMetadata().Register();
createDesigner();
}
public void createDesigner()
{
WorkflowDesigner designer = new WorkflowDesigner();
Sequence root = new Sequence()
{
Activities = {
new Assign(),
new WriteLine()}
};
designer.Load(root);
Grid.SetColumn(designer.View, 0);
// Create ExpressionEditorService
this.expressionEditorService = new MyEditorService();
// Publish the instance of MyEditorService.
designer.Context.Services.Publish<IExpressionEditorService>(this.expressionEditorService);
MyGrid.Children.Add(designer.View);
}
}
}
Notas
Se você estiver usando um controle ExpressionTextBox em um designer de atividade personalizado, não é necessário criar e destruir editores de expressão usando os CreateExpressionEditor métodos e CloseExpressionEditors da IExpressionEditorService interface. A ExpressionTextBox classe gerencia isso para você.