AvalonEdit
Code Completion

AvalonEdit comes with a code completion drop down window. You only have to handle the text entering events to determine when you want to show the window; all the UI is already done for you.

Usage of the Code Completion Window
C# Copy imageCopy
    // in the constructor:
    textEditor.TextArea.TextEntering += textEditor_TextArea_TextEntering;
    textEditor.TextArea.TextEntered += textEditor_TextArea_TextEntered;
}

CompletionWindow completionWindow;

void textEditor_TextArea_TextEntered(object sender, TextCompositionEventArgs e)
{
    if (e.Text == ".") {
        // Open code completion after the user has pressed dot:
        completionWindow = new CompletionWindow(textEditor.TextArea);
        IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;
        data.Add(new MyCompletionData("Item1"));
        data.Add(new MyCompletionData("Item2"));
        data.Add(new MyCompletionData("Item3"));
        completionWindow.Show();
        completionWindow.Closed += delegate {
            completionWindow = null;
        };
    }
}

void textEditor_TextArea_TextEntering(object sender, TextCompositionEventArgs e)
{
    if (e.Text.Length > 0 && completionWindow != null) {
        if (!char.IsLetterOrDigit(e.Text[0])) {
            // Whenever a non-letter is typed while the completion window is open,
            // insert the currently selected element.
            completionWindow.CompletionList.RequestInsertion(e);
        }
    }
    // Do not set e.Handled=true.
    // We still want to insert the character that was typed.
}

This code will open the code completion window whenever '.' is pressed. By default, the CompletionWindow only handles key presses like Tab and Enter to insert the currently selected item. To also make it complete when keys like '.' or ';' are pressed, we attach another handler to the TextEntering event and tell the completion window to insert the selected item.

The CompletionWindow will actually never have focus - instead, it hijacks the WPF keyboard input events on the text area and passes them through its ListBox. This allows selecting entries in the completion list using the keyboard and normal typing in the editor at the same time.

Here is the implementation of the MyCompletionData class used in the code above:

C# Copy imageCopy
/// Implements AvalonEdit ICompletionData interface to provide the entries in the
/// completion drop down.
public class MyCompletionData : ICompletionData
{
    public MyCompletionData(string text)
    {
        this.Text = text;
    }

    public System.Windows.Media.ImageSource Image {
        get { return null; }
    }

    public string Text { get; private set; }

    // Use this property if you want to show a fancy UIElement in the list.
    public object Content {
        get { return this.Text; }
    }

    public object Description {
        get { return "Description for " + this.Text; }
    }

    public void Complete(TextArea textArea, ISegment completionSegment,
        EventArgs insertionRequestEventArgs)
    {
        textArea.Document.Replace(completionSegment, this.Text);
    }
}
Both the content and the description shown may be any content acceptable in WPF, including custom UIElements. You may also implement custom logic in the Complete method if you want to do more than simply inserting the text. The insertionRequestEventArgs can help decide which kind of insertion the user wants - depending on how the insertion was triggered, it is an instance of TextCompositionEventArgs, KeyEventArgs or MouseEventArgs.

Code Completion for C#

Full C# code completion is not in the scope of AvalonEdit. You will need a C# parser, a C# type system, and the ability to resolve C# expressions in your type system.

If you want to learn how this is handled in SharpDevelop, please see: Code Completion in SharpDevelop