我正在寻找一个WPF拼写检查控件(类似于内置功能,但支持更多字典) . 我需要它具有你的类型功能(红色下划线) . 它还应该支持超过4种语言,而不是内置的.NET 4.0拼写检查(例如英语,西班牙语,德语,意大利语和俄语支持会很棒) .
我更喜欢控件具有可在商业Windows应用程序中使用的MIT或BSD许可证 . 源代码很棒,因为我想将拼写建议集成到我的自定义右键单击上下文菜单中 .
我通过添加自己的SpellCheckerBehavior将AvalonEdit与NHunspell结合起来 . 可以在github找到此示例项目 . 它实现如下:
<avalonEdit:TextEditor xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" Name="editor"> <avalonEdit:TextEditor.ContextMenu> <ContextMenu> <MenuItem Command="Undo" /> <MenuItem Command="Redo" /> <Separator/> <MenuItem Command="Cut" /> <MenuItem Command="Copy" /> <MenuItem Command="Paste" /> </ContextMenu> </avalonEdit:TextEditor.ContextMenu> <i:Interaction.Behaviors> <local:SpellCheckerBehavior /> </i:Interaction.Behaviors> </avalonEdit:TextEditor>
...修改我的MainWindow的构造函数,如下所示:
public MainWindow() { SpellChecker.Default.HunspellInstance = new Hunspell("German.aff", "German.dic"); editor.TextArea.TextView.LineTransformers.Add(new SpellCheckerColorizer()); }
...并将以下类添加到我的项目中以进行集成:
using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Windows; using System.Windows.Controls; using System.Windows.Interactivity; using System.Windows.Media; using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; using NHunspell; namespace Martin { public class SpellChecker { static Lazy<SpellChecker> defaultInstance = new Lazy<SpellChecker>(() => new SpellChecker()); public static SpellChecker Default { get { return defaultInstance.Value; } } public Hunspell HunspellInstance { get; set; } public class Word { public int Index { get; set; } public string Value { get; set; } } static IEnumerable<Word> FindWords(string text) { foreach (Match m in new Regex(@"\w+").Matches(text)) { yield return new Word() { Index = m.Index, Value = m.Value }; } } public IEnumerable<Word> FindSpellingErrors(string text) { foreach (var word in FindWords(text)) { if (!Spell(word.Value)) { yield return word; } } } public bool Spell(string word) { return HunspellInstance.Spell(word); } public List<string> Suggest(string word) { return HunspellInstance.Suggest(word); } } public class SpellCheckerBehavior : Behavior<TextEditor> { TextEditor textEditor; List<Control> originalItems; protected override void OnAttached() { textEditor = AssociatedObject; if (textEditor != null) { textEditor.ContextMenuOpening += new ContextMenuEventHandler(TextEditorContextMenuOpening); textEditor.TextArea.MouseRightButtonDown += new System.Windows.Input.MouseButtonEventHandler(TextAreaMouseRightButtonDown); originalItems = textEditor.ContextMenu.Items.OfType<Control>().ToList(); } base.OnAttached(); } protected override void OnDetaching() { if (textEditor != null) { textEditor.ContextMenuOpening -= new ContextMenuEventHandler(TextEditorContextMenuOpening); textEditor.TextArea.MouseRightButtonDown -= new System.Windows.Input.MouseButtonEventHandler(TextAreaMouseRightButtonDown); originalItems = null; textEditor = null; } base.OnDetaching(); } void TextAreaMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { var position = textEditor.GetPositionFromPoint(e.GetPosition(textEditor)); if (position.HasValue) { textEditor.TextArea.Caret.Position = position.Value; } } void TextEditorContextMenuOpening(object sender, ContextMenuEventArgs e) { foreach (Control item in textEditor.ContextMenu.Items.OfType<Control>().ToList()) { if (originalItems.Contains(item)) { continue; } textEditor.ContextMenu.Items.Remove(item); } var position = textEditor.TextArea.Caret.Position; Match word = null; Regex r = new Regex(@"\w+"); var line = textEditor.Document.GetText(textEditor.Document.GetLineByNumber(position.Line)); foreach (Match m in r.Matches(line)) { if (m.Index >= position.VisualColumn) { break; } word = m; } if (null == word || position.Column > word.Index + word.Value.Length || SpellChecker.Default.Spell(word.Value)) { return; } textEditor.ContextMenu.Items.Insert(0, new Separator()); var suggestions = SpellChecker.Default.Suggest(word.Value); if (0 == suggestions.Count) { textEditor.ContextMenu.Items.Insert(0, new MenuItem() { Header = "<No suggestions found>", IsEnabled = false }); return; } foreach (string suggestion in suggestions) { var item = new MenuItem { Header = suggestion, FontWeight = FontWeights.Bold }; item.Tag = new Tuple<int, int>( textEditor.Document.GetOffset(position.Line, word.Index + 1), word.Value.Length); item.Click += ItemClick; textEditor.ContextMenu.Items.Insert(0, item); } } private void ItemClick(object sender, RoutedEventArgs e) { var item = sender as MenuItem; if (null == item) { return; } var segment = item.Tag as Tuple<int, int>; if (null == segment) { return; } textEditor.Document.Replace(segment.Item1, segment.Item2, item.Header.ToString()); } } public class SpellCheckerColorizer : DocumentColorizingTransformer { private readonly TextDecorationCollection textDecorationCollection; public SpellCheckerColorizer() { textDecorationCollection = new TextDecorationCollection(); textDecorationCollection.Add(new TextDecoration() { Pen = new Pen { Thickness = 1, DashStyle = DashStyles.Dot, Brush = new SolidColorBrush(Colors.Red) }, PenThicknessUnit = TextDecorationUnit.FontRecommended }); } protected override void ColorizeLine(DocumentLine line) { var lineText = CurrentContext.Document.Text .Substring(line.Offset, line.Length); foreach (var error in SpellChecker.Default.FindSpellingErrors(lineText)) { base.ChangeLinePart(line.Offset + error.Index, line.Offset + error.Index + error.Value.Length, (VisualLineElement element) => element.TextRunProperties.SetTextDecorations(textDecorationCollection)); } } } }
AvalonEdit(http://www.codeproject.com/KB/edit/AvalonEdit.aspx)是在WPF中为SharpDevelop从头开始编写的 . 哦快速谷歌的奇迹 .
如果你一次只使用一种语言(但可以切换),你可以使用默认的WPF功能(http://joshsmithonwpf.wordpress.com/2007/02/17/spellchecking-and-suggested-spellings-in-a-textbox/)
2 回答
我通过添加自己的SpellCheckerBehavior将AvalonEdit与NHunspell结合起来 . 可以在github找到此示例项目 . 它实现如下:
...修改我的MainWindow的构造函数,如下所示:
...并将以下类添加到我的项目中以进行集成:
AvalonEdit(http://www.codeproject.com/KB/edit/AvalonEdit.aspx)是在WPF中为SharpDevelop从头开始编写的 . 哦快速谷歌的奇迹 .
如果你一次只使用一种语言(但可以切换),你可以使用默认的WPF功能(http://joshsmithonwpf.wordpress.com/2007/02/17/spellchecking-and-suggested-spellings-in-a-textbox/)