Wpf 只加载一次自定义词典。拼写检查器
下面是代码:Wpf 只加载一次自定义词典。拼写检查器,wpf,dictionary,spell-checking,Wpf,Dictionary,Spell Checking,下面是代码: IList dictionaries = SpellCheck.GetCustomDictionaries(tb); Uri uri = new Uri("Russian.lex", UriKind.Relative); dictionaries.Add(uri); tb.SpellCheck.IsEnabled = true; 问题是,我必须使用拼写检查创建多个文本框,分配customdictionary的唯一方法是将Uri传递给TextBoxBase.CustomDictio
IList dictionaries = SpellCheck.GetCustomDictionaries(tb);
Uri uri = new Uri("Russian.lex", UriKind.Relative);
dictionaries.Add(uri);
tb.SpellCheck.IsEnabled = true;
问题是,我必须使用拼写检查创建多个文本框,分配customdictionary的唯一方法是将Uri传递给TextBoxBase.CustomDictionaries.Add()。所以每次我设置SpellCheck.IsEnabled时都会有3-5秒的延迟,我认为这是从硬盘加载文件造成的。最重要的是,似乎每一次加载字典,它都会永远留在记忆中
关于如何一次性加载自定义词典并重新使用它的任何提示?您可以创建一个包含自定义词典的临时文件 它是这样实现的,
FileSystemHelper
只是一个helper类,但它只是使用Path
和目录
类来创建一个文件
public Uri CreateCustomLexiconDictionary()
{
if (!_fileSystemHelper.Exists(_customDictionaryLocation))
{
_fileSystemHelper.AppendLine(_customDictionaryLocation, @"Line");
}
if ((_fileSystemHelper.Exists(_customDictionaryLocation) && customDictionaries.Count == 0))
return new Uri("file:///" + _customDictionaryLocation);
}
}
从那里,您使用的每个文本框
都可以调用CreateCustomLexiconDictionary
,然后将其添加到拼写检查的字典
对象中
IList dictionaries = SpellCheck.GetCustomDictionaries(tb);
dictionaries.Add(CreateCustomLexiconDictionary());
完成后,您可以将URI
删除到字典中,以便它将其清除。完成后还要删除该文件
另外,RichTextBox
拼写检查速度非常慢,微软已经意识到了这一点。在经历了多次错误的开始之后,我认为我已经成功了
我用反射四处搜寻,直到找到自定义词典的内部表示(ILexicon)。然后,我将此ILexicon分配给每个新的文本内容。这些接口都不是公共的,因此我在未来的版本中,甚至在一个服务包中都有被破坏的明显风险,但它在今天仍然有效。[这在.net 4.6中会中断并变得不必要,请参见下文。]
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using Melville.Library.ReflectionHelpers;
namespace PhotoDoc.Wpf.Controls.FormControls
{
public static class DynamicDictionaryLoader
{
private static string dictionaryLocation;
public static string DictionaryLocation
{
get
{
if (dictionaryLocation == null)
{
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
dictionaryLocation = Path.Combine(path, "UsMedicalEnglish.dic");
}
return dictionaryLocation;
}
}
public static void AddDictionary(TextBoxBase targetControl)
{
try
{
InnerLoadDictionary(targetControl);
}
catch (UriFormatException)
{
// occasionaly occurrs in odd instalations. You just don't get the medical dictionary
}
catch (ArgumentException)
{
// this is a rare bug that I think may be a race condition inside WPF. I've only triggered it 2-3 times.
// One time was when I had seven files open at once. The other, ironically, was when activating the
// default text for a field.
// In this rare error exception, you will just get all your medical words flagged as mispellings for that
// textbox. I won't know for a while if this worked, because I only saw the bug after months of daily use
// of the program.
}
}
private static object oldDictionary = null;
private static object dictionaryLoaderLock = new Object();
private static void InnerLoadDictionary(TextBoxBase targetControl)
{
var dictionary = SpellCheck.GetCustomDictionaries(targetControl);
if (dictionary.Count < 1)
{
var speller = dictionary.GetProperty("Speller");
var uriMap = speller.GetProperty("UriMap") as IDictionary;
if (uriMap.Count > 0) return; // already initalized
lock (dictionaryLoaderLock)
{
var dictionaryUri = new Uri(DictionaryLocation, UriKind.Absolute);
if (oldDictionary == null)
{
dictionary.Add(dictionaryUri);
oldDictionary = uriMap.Values.OfType<object>().FirstOrDefault();
}
else
{
if (!(bool) speller.Call("EnsureInitialized")) return;
uriMap.Add(dictionaryUri, oldDictionary);
GetContext(
speller.GetField("_spellerInterop").
GetField("_textChunk") as ITextChunk).
AddLexicon(oldDictionary.GetProperty("Lexicon") as ILexicon);
speller.Call("ResetErrors");
}
}
}
}
private static ITextContext GetContext(ITextChunk chunk)
{
ITextContext ret = null;
chunk.get_Context(out ret);
return ret;
}
#region Com Imports
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("549F997E-0EC3-43d4-B443-2BF8021010CF")]
private interface ITextChunk
{
void stub_get_InputText();
void stub_put_InputText();
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void SetInputArray([In] IntPtr inputArray, Int32 size);
void stub_RegisterEngine();
void stub_UnregisterEngine();
void stub_get_InputArray();
void stub_get_InputArrayRange();
void stub_put_InputArrayRange();
void get_Count(out Int32 val);
void get_Item(Int32 index, [MarshalAs(UnmanagedType.Interface)] out object val);
void stub_get__NewEnum();
[SecurityCritical]
void get_Sentences([MarshalAs(UnmanagedType.Interface)] out object val);
void stub_get_PropertyCount();
void stub_get_Property();
void stub_put_Property();
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void get_Context([MarshalAs(UnmanagedType.Interface)] out ITextContext val);
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void put_Context([MarshalAs(UnmanagedType.Interface)] ITextContext val);
void stub_get_Locale();
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void put_Locale(Int32 val);
void stub_get_IsLocaleReliable();
void stub_put_IsLocaleReliable();
void stub_get_IsEndOfDocument();
void stub_put_IsEndOfDocument();
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void GetEnumerator([MarshalAs(UnmanagedType.Interface)] out object val);
void stub_ToString();
void stub_ProcessStream();
void get_ReuseObjects(out bool val);
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void put_ReuseObjects(bool val);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("B6797CC0-11AE-4047-A438-26C0C916EB8D")]
private interface ITextContext
{
void stub_get_PropertyCount();
void stub_get_Property();
void stub_put_Property();
void stub_get_DefaultDialectCount();
void stub_get_DefaultDialect();
void stub_AddDefaultDialect();
void stub_RemoveDefaultDialect();
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void get_LexiconCount([MarshalAs(UnmanagedType.I4)] out Int32 lexiconCount);
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void get_Lexicon(Int32 index, [MarshalAs(UnmanagedType.Interface)] out ILexicon lexicon);
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void AddLexicon([In, MarshalAs(UnmanagedType.Interface)] ILexicon lexicon);
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void RemoveLexicon([In, MarshalAs(UnmanagedType.Interface)] ILexicon lexicon);
void stub_get_Version();
void stub_get_ResourceLoader();
void stub_put_ResourceLoader();
[SecurityCritical, SuppressUnmanagedCodeSecurity]
void get_Options([MarshalAs(UnmanagedType.Interface)] out object val);
void get_Capabilities(Int32 locale, [MarshalAs(UnmanagedType.Interface)] out object val);
void stub_get_Lexicons();
void stub_put_Lexicons();
void stub_get_MaxSentences();
void stub_put_MaxSentences();
void stub_get_IsSingleLanguage();
void stub_put_IsSingleLanguage();
void stub_get_IsSimpleWordBreaking();
void stub_put_IsSimpleWordBreaking();
void stub_get_UseRelativeTimes();
void stub_put_UseRelativeTimes();
void stub_get_IgnorePunctuation();
void stub_put_IgnorePunctuation();
void stub_get_IsCaching();
void stub_put_IsCaching();
void stub_get_IsShowingGaps();
void stub_put_IsShowingGaps();
void stub_get_IsShowingCharacterNormalizations();
void stub_put_IsShowingCharacterNormalizations();
void stub_get_IsShowingWordNormalizations();
void stub_put_IsShowingWordNormalizations();
void stub_get_IsComputingCompounds();
void stub_put_IsComputingCompounds();
void stub_get_IsComputingInflections();
void stub_put_IsComputingInflections();
void stub_get_IsComputingLemmas();
void stub_put_IsComputingLemmas();
void stub_get_IsComputingExpansions();
void stub_put_IsComputingExpansions();
void stub_get_IsComputingBases();
void stub_put_IsComputingBases();
void stub_get_IsComputingPartOfSpeechTags();
void stub_put_IsComputingPartOfSpeechTags();
void stub_get_IsFindingDefinitions();
void stub_put_IsFindingDefinitions();
void stub_get_IsFindingDateTimeMeasures();
void stub_put_IsFindingDateTimeMeasures();
void stub_get_IsFindingPersons();
void stub_put_IsFindingPersons();
void stub_get_IsFindingLocations();
void stub_put_IsFindingLocations();
void stub_get_IsFindingOrganizations();
void stub_put_IsFindingOrganizations();
void stub_get_IsFindingPhrases();
void stub_put_IsFindingPhrases();
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("004CD7E2-8B63-4ef9-8D46-080CDBBE47AF")]
internal interface ILexicon
{
void ReadFrom([MarshalAs(UnmanagedType.BStr)]string fileName);
void stub_WriteTo();
void stub_GetEnumerator();
void stub_IndexOf();
void stub_TagFor();
void stub_ContainsPrefix();
void stub_Add();
void stub_Remove();
void stub_Version();
void stub_Count();
void stub__NewEnum();
void stub_get_Item();
void stub_set_Item();
void stub_get_ItemByName();
void stub_set_ItemByName();
void stub_get0_PropertyCount();
void stub_get1_Property();
void stub_set_Property();
void stub_get_IsReadOnly();
}
#endregion
}
}
静态类
?首次使用时加载的实用程序类?拼写检查
和拼写检查。自定义词典
是只读属性。使用XamlWriter
尝试使用加载的字典克隆静态文本框
也失败,字典将丢失。恕我直言,请你在回答之前试着研究一下这个问题好吗?恕我直言,请你在回答之前试着研究一下这个问题好吗?。。。首先,这不表示尊重。其次,@crashmstr在他们的评论中花了时间给你提供了一个建议。。。这不是答案,所以他们没有试图回答你的问题。第三,他们没有暗示你认为他们是什么,所以你编造了你自己的答案,并指责他们没有起作用。这是一个非常糟糕的节目,尤其是来自这个网站的一个初级会员。我的不好,我已经考虑过这个建议作为一个答案。很抱歉,您不需要在.net 4.6及更高版本中使用此解决方案。应用于.NET4.6中任何文本框的词典都会自动应用于每个文本框和richtextbox。嗨,约翰!感谢分享解决方案。遗憾的是,我没有时间检查它是否有效,而且这个问题对我来说已经很久没有了,因为我们正在使用devexpress控件,而且他们已经提供了将拼写检查器与本机wpf文本框一起使用的功能。我会把你的帖子标记为答案。希望它能帮助您在.net 4.6及更高版本中不需要此解决方案。应用于.NET4.6中任何文本框的词典会自动应用于每个文本框和richtextbox。
using System;
using System.Linq;
using System.Reflection;
namespace Melville.Library.ReflectionHelpers
{
public static class ReflectionHelper
{
public static void SetField(this object target, string property, object value)
{
Field(target, property).SetValue(target, value);
}
public static object GetField(this object target, string name)
{
return Field(target, name).GetValue(target);
}
private static FieldInfo Field(object target, string name)
{
return target.GetType().GetField(name,
BindingFlags.NonPublic | BindingFlags.Public |BindingFlags.GetField|
BindingFlags.FlattenHierarchy|BindingFlags.Instance);
}
public static object GetProperty(this object target, string name)
{
return Property(target, name).
GetValue(target);
}
private static PropertyInfo Property(object target, string name)
{
return target.GetType().GetProperty(name,
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetProperty|BindingFlags.FlattenHierarchy|BindingFlags.Instance);
}
public static void SetProperty(this object target, string property, object value)
{
Property(target, property).SetValue(target, value);
}
private const BindingFlags MethodBindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.FlattenHierarchy | BindingFlags.Instance;
private static MethodInfo Method(object target, string name, Type[] types)
{
return target.GetType().GetMethod(name,
MethodBindingFlags, null, CallingConventions.Any, types, null) ;
}
public static MethodInfo Method(object target, string name)
{
var methodInfos = target.GetType().GetMethods(MethodBindingFlags);
return methodInfos.FirstOrDefault(i=>i.Name.Equals(name, StringComparison.Ordinal));
}
public static object Call(this object target, string methodName, params object[] paramenters)
{
return Method(target, methodName, paramenters.Select(i => i.GetType()).ToArray()).Invoke(target, paramenters);
}
}
}