About go:Part.TextEditable


#1

How can I use the interface “ITextEditor”?

Can you give me a sample of ITextEditor?

Because I need to judge whether Text meets my logic before the TextBlock finishes editing.


#2

Here’s how the default text editor is implemented:

  internal class TextBoxEditor : ITextEditor {
    public TextEditingTool TextEditingTool {
      get { return _TextEditingTool; }
      set {
        _TextEditingTool = value;
        if (value != null) {
          TextBox box = this.TextBox;
          if (box != null) {
            this.Text = value.TextBlock.Text;
            box.SelectAll();
            box.KeyDown += (s, e) => HandleKey(e);
            box.TextChanged += (s, e) => LayoutBox(box);
            box.GotFocus += (s, e) => RaiseFocus(s, e);
            box.LostFocus += (s, e) => LostFocus();
            LayoutBox(box);  // initial positioning
            Focus();
            //?? support real-time editing
          }
        }
      }
    }
    private TextEditingTool _TextEditingTool;

    public void Focus() {
      TextBox box = this.TextBox;
      if (box != null) box.Focus();
    }

    public event EventHandler GotFocus;

    public String Text {
      get {
        TextBox box = this.TextBox;
        if (box != null) return box.Text;
        return "";
      }
      set {
        TextBox box = this.TextBox;
        if (box != null) box.Text = value;
      }
    }

    public bool IsValidText(String oldstring, String newstring) {
      return true;
    }

    public TextBox TextBox {
      get {
        if (this.TextEditingTool == null) return null;
        if (this.TextEditingTool.EditorAdornment == null) return null;
        return this.TextEditingTool.EditorAdornment.FindDescendant(e => e is TextBox) as TextBox;
      }
    }

    private void RaiseFocus(Object s, EventArgs e) {
      if (this.GotFocus != null) this.GotFocus(s, e);
    }

    private void LostFocus() {
      TextEditingTool tool = this.TextEditingTool;
      if (tool != null) tool.AcceptText(TextEditingReason.LostFocus);
    }

    private void HandleKey(KeyEventArgs e) {
      if (e.Key == Key.Enter) {
        TextBox box = this.TextBox;
        if (box != null && !box.AcceptsReturn) {
          TextEditingTool tool = this.TextEditingTool;
          if (tool != null) tool.AcceptText(TextEditingReason.Enter);
          return;
        }
      } else if (e.Key == Key.Tab) {
        TextBox box = this.TextBox;
        if (box != null && !box.AcceptsTab) {
          TextEditingTool tool = this.TextEditingTool;
          if (tool != null) tool.AcceptText(TextEditingReason.Tab);
          return;
        }
      }
    }

    private void LayoutBox(TextBox box) {
      if (box == null) return;
      TextEditingTool tool = this.TextEditingTool;
      if (tool == null) return;
      TextBlock block = tool.TextBlock;
      if (block == null) return;
      Adornment edad = tool.EditorAdornment;
      if (edad == null) return;
      Thickness thick = box.BorderThickness;
      Thickness pad = box.Padding;
      if (block.TextWrapping != TextWrapping.NoWrap) {
        double w = MeasureWrappedTextWidth(box.Text, box, block);
        Size es = edad.GetEffectiveSize(block);
        double ww = Math.Max(w, es.Width);  // at least existing width
        box.MaxWidth = ww + thick.Left + thick.Right + pad.Left + pad.Right + 6;  //??? hard-coded sizes
        //Diagram.Debug(Diagram.Str(ds) + Diagram.Str(es) + " ww: " + Diagram.Str(ww) + " maxw: " + Diagram.Str(box.MaxWidth));
      }
      edad.Remeasure();
    }

    private double MeasureWrappedTextWidth(String s, TextBox box, TextBlock block) {
      if (s == null) return 0;
      TextBlock tb = this.MTB;
      if (tb == null) {
        tb = new TextBlock();
        this.MTB = tb;
      }
      // make this TextBlock look like the TextBox
      tb.FontFamily = box.FontFamily;
      tb.FontStretch = box.FontStretch;
      tb.FontStyle = box.FontStyle;
      tb.FontWeight = box.FontWeight;
      tb.TextAlignment = box.TextAlignment;
      //tb.TextDecorations = box.TextDecorations;
      tb.TextWrapping = box.TextWrapping;
      // or like the TextBlock
      tb.MinWidth = block.MinWidth;
      tb.MaxWidth = block.MaxWidth;
      Part.SetTextAspectRatio(tb, Part.GetTextAspectRatio(block));
      // initial text
      tb.Text = s;
      return NodePanel.MeasureWrappedTextWidth(tb, new Size(tb.MaxWidth, tb.MaxHeight));
    }
    private TextBlock MTB { get; set; }
  }

Please note that this refers to internal methods that are undocumented – you’ll need to implement something else instead.