WPF 拼写检查未在选项卡中加载自定义词典
WPF spell checking not loading a custom dictionary in a tab
如果我在App.xaml中全局启用拼写检查...
<Application.Resources>
<Style TargetType="TextBox">
<Setter Property="SpellCheck.IsEnabled"
Value="True" />
</Style>
</Application.Resources>
...然后我在应用程序的所有文本框中都得到了红色下划线和拼写检查,无论它们在哪里。
如果我想添加一个自定义词典,那么我必须使用类似于this SO answer中所示的代码,然后按如下方式调用它...
public MainWindow() {
InitializeComponent();
Loaded += (_, __) => Helpers.SetCustomDictionary(this);
}
(辅助方法的代码显示在下方)
这适用于 window 首次加载时显示的文本框,但如果我有一个选项卡控件,并且默认选项卡有一个文本框,则不会应用自定义词典。
我尝试在加载选项卡时调用 Helpers.SetCustomDictionary(this)
,但这也不起作用。我可以看到该方法在 window 加载时被调用,我的猜测是在那个阶段,选项卡的内容尚未创建,因此该方法找不到它们来设置自定义字典。
我发现唯一有效的方法是在加载单个文本框本身时调用它。但是,这很痛苦,因为我必须单独为每个文本框执行此操作。
有谁知道让自定义词典适用于 window 首次加载时不可见的文本框的方法吗?
谢谢
P.S。这是辅助方法的代码,它使用链接的 SO 回复中显示的 FindAllChildren()
方法...
public static void SetCustomDictionary(DependencyObject parent) {
Uri uri = new Uri("pack://application:,,,/CustomDictionary.lex");
List<TextBox> textBoxes = new List<TextBox>();
FindAllChildren(parent, ref textBoxes);
foreach (TextBox tb in textBoxes) {
if (tb.SpellCheck.IsEnabled && !tb.SpellCheck.CustomDictionaries.Contains(uri)) {
tb.SpellCheck.CustomDictionaries.Add(uri);
}
}
}
可能有更好的解决方案,但您可以使用 App.xaml.cs 的 OnStartup
事件为每个 TextBox
设置字典,当它加载单个事件处理程序时:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
EventManager.RegisterClassHandler(typeof(TextBox), FrameworkElement.LoadedEvent, new RoutedEventHandler(TextBox_OnLoaded));
}
private void TextBox_OnLoaded(object sender, RoutedEventArgs e)
{
// Set custom dictionary here.
}
}
虽然 Dean Kuga 的回答看起来很有希望,但它对我不起作用。经过更多搜索后,似乎存在一个错误,在大多数情况下会阻止 Loaded
事件被触发。在对解决该问题的 SO question where I saw this mentioned, Marcin Wisnicki linked to some code he wrote 的答案的评论中。
因为我只希望它适用于文本框,所以我稍微简化了他的代码。如果它对任何人有帮助,这是我的简化代码...
public partial class App {
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
EventManager.RegisterClassHandler(typeof(Window),
FrameworkElement.SizeChangedEvent, new RoutedEventHandler(OnSizeChanged));
EventManager.RegisterClassHandler(typeof(TextBox),
FrameworkElement.LoadedEvent, new RoutedEventHandler(OnLoaded), true);
}
private static void OnSizeChanged(object sender, RoutedEventArgs e) {
SetMyInitialised((Window)sender, true);
}
private static void OnLoaded(object sender, RoutedEventArgs e) {
if (e.OriginalSource is TextBox) {
TextBox tb = (TextBox)e.OriginalSource;
Helpers.SetCustomDictionaryTextBox(tb);
}
}
#region MyInitialised dependency property
public static readonly DependencyProperty MyInitialisedProperty =
DependencyProperty.RegisterAttached("MyInitialised",
typeof(bool),
typeof(App),
new FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.Inherits,
OnMyInitialisedChanged));
private static void OnMyInitialisedChanged(DependencyObject dpo,
DependencyPropertyChangedEventArgs ev) {
if ((bool)ev.NewValue && dpo is FrameworkElement) {
(dpo as FrameworkElement).Loaded += delegate { };
}
}
public static void SetMyInitialised(UIElement element, bool value) {
element.SetValue(MyInitialisedProperty, value);
}
public static bool GetMyInitialised(UIElement element) {
return (bool)element.GetValue(MyInitialisedProperty);
}
#endregion MyInitialised
}
因为是英文,所以我把"Initialized"改成了"Initialised",除此之外,DP代码是一样的
希望这对某人有所帮助。
如果我在App.xaml中全局启用拼写检查...
<Application.Resources>
<Style TargetType="TextBox">
<Setter Property="SpellCheck.IsEnabled"
Value="True" />
</Style>
</Application.Resources>
...然后我在应用程序的所有文本框中都得到了红色下划线和拼写检查,无论它们在哪里。
如果我想添加一个自定义词典,那么我必须使用类似于this SO answer中所示的代码,然后按如下方式调用它...
public MainWindow() {
InitializeComponent();
Loaded += (_, __) => Helpers.SetCustomDictionary(this);
}
(辅助方法的代码显示在下方)
这适用于 window 首次加载时显示的文本框,但如果我有一个选项卡控件,并且默认选项卡有一个文本框,则不会应用自定义词典。
我尝试在加载选项卡时调用 Helpers.SetCustomDictionary(this)
,但这也不起作用。我可以看到该方法在 window 加载时被调用,我的猜测是在那个阶段,选项卡的内容尚未创建,因此该方法找不到它们来设置自定义字典。
我发现唯一有效的方法是在加载单个文本框本身时调用它。但是,这很痛苦,因为我必须单独为每个文本框执行此操作。
有谁知道让自定义词典适用于 window 首次加载时不可见的文本框的方法吗?
谢谢
P.S。这是辅助方法的代码,它使用链接的 SO 回复中显示的 FindAllChildren()
方法...
public static void SetCustomDictionary(DependencyObject parent) {
Uri uri = new Uri("pack://application:,,,/CustomDictionary.lex");
List<TextBox> textBoxes = new List<TextBox>();
FindAllChildren(parent, ref textBoxes);
foreach (TextBox tb in textBoxes) {
if (tb.SpellCheck.IsEnabled && !tb.SpellCheck.CustomDictionaries.Contains(uri)) {
tb.SpellCheck.CustomDictionaries.Add(uri);
}
}
}
可能有更好的解决方案,但您可以使用 App.xaml.cs 的 OnStartup
事件为每个 TextBox
设置字典,当它加载单个事件处理程序时:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
EventManager.RegisterClassHandler(typeof(TextBox), FrameworkElement.LoadedEvent, new RoutedEventHandler(TextBox_OnLoaded));
}
private void TextBox_OnLoaded(object sender, RoutedEventArgs e)
{
// Set custom dictionary here.
}
}
虽然 Dean Kuga 的回答看起来很有希望,但它对我不起作用。经过更多搜索后,似乎存在一个错误,在大多数情况下会阻止 Loaded
事件被触发。在对解决该问题的 SO question where I saw this mentioned, Marcin Wisnicki linked to some code he wrote 的答案的评论中。
因为我只希望它适用于文本框,所以我稍微简化了他的代码。如果它对任何人有帮助,这是我的简化代码...
public partial class App {
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
EventManager.RegisterClassHandler(typeof(Window),
FrameworkElement.SizeChangedEvent, new RoutedEventHandler(OnSizeChanged));
EventManager.RegisterClassHandler(typeof(TextBox),
FrameworkElement.LoadedEvent, new RoutedEventHandler(OnLoaded), true);
}
private static void OnSizeChanged(object sender, RoutedEventArgs e) {
SetMyInitialised((Window)sender, true);
}
private static void OnLoaded(object sender, RoutedEventArgs e) {
if (e.OriginalSource is TextBox) {
TextBox tb = (TextBox)e.OriginalSource;
Helpers.SetCustomDictionaryTextBox(tb);
}
}
#region MyInitialised dependency property
public static readonly DependencyProperty MyInitialisedProperty =
DependencyProperty.RegisterAttached("MyInitialised",
typeof(bool),
typeof(App),
new FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.Inherits,
OnMyInitialisedChanged));
private static void OnMyInitialisedChanged(DependencyObject dpo,
DependencyPropertyChangedEventArgs ev) {
if ((bool)ev.NewValue && dpo is FrameworkElement) {
(dpo as FrameworkElement).Loaded += delegate { };
}
}
public static void SetMyInitialised(UIElement element, bool value) {
element.SetValue(MyInitialisedProperty, value);
}
public static bool GetMyInitialised(UIElement element) {
return (bool)element.GetValue(MyInitialisedProperty);
}
#endregion MyInitialised
}
因为是英文,所以我把"Initialized"改成了"Initialised",除此之外,DP代码是一样的
希望这对某人有所帮助。