[英]Can't apply style to RichTextBox elements based on DependencyProperty
我有一个控件,该控件继承了带有DependencyProperty
RichTextBox
(我将其称为MyRichTextBox
),该MyRichTextBox
为某些文本元素类型定义了样式。 与ItemsControl.ItemContainerStyle
相似,此样式将根据实例应用于其某些子项。
我尝试过两种不同的方法,但两种方法均无效:
Button
,并在托管InlineUIContainer
,我们会打电话给这个MyTextElement
),我想创建一个基于新的风格MyRichTextBox.ItemContainerStyle
并分配MyTextElement
新样式。 MyRichTextBox.ItemContainerStyle
更改时,基于MyRichTextBox.ItemContainerStyle
创建新样式,然后添加到MyRichTextBox
的资源中。 两种方法都会导致以下意外异常:
An unhandled exception of type 'MS.Internal.PtsHost.UnsafeNativeMethods.PTS.SecondaryException' occurred in PresentationFramework.dll
没有提供任何其他信息,并且在研究此异常时,我还没有发现任何东西,因为它与RichTextBox
或以编程方式分配样式有关。 一些文章指出该错误是线程问题。 但是,我并不想在不同的线程创建样式和创建/分配样式而不使其基于MyRichTextBox.ItemContainerStyle
确实工作。
这是使用方法2的控件的外观(为简洁起见,我将方法1排除在外了,因为它做同样的事情,只是方式不同):
public class MyRichTextBox : RichTextBox
{
public static DependencyProperty ItemContainerStyleProperty = DependencyProperty.Register("ItemContainerStyle", typeof(Style), typeof(MyRichTextBox), new FrameworkPropertyMetadata(default(Style), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnItemContainerStyleChanged));
public Style ItemContainerStyle
{
get
{
return (Style)GetValue(ItemContainerStyleProperty);
}
set
{
SetValue(ItemContainerStyleProperty, value);
}
}
static void OnItemContainerStyleChanged(DependencyObject Object, DependencyPropertyChangedEventArgs e)
{
(Object as MyRichTextBox).OnItemContainerStyleChanged((Style)e.OldValue, (Style)e.NewValue);
}
protected virtual void OnItemContainerStyleChanged(Style OldValue, Style NewValue)
{
//Make sure the old style is gone
if (OldValue != null)
Resources.Remove(OldValue.TargetType);
if (NewValue != null)
{
//This line does not attempt to utilize the specified style, but is stable
Resources.Add(NewValue.TargetType, new Style(NewValue.TargetType));
//This line attempts to utilize the specified style, but is unstable
Resources.Add(NewValue.TargetType, new Style(NewValue.TargetType, NewValue));
}
}
}
最终,我希望能够做到这一点:
<Controls:MyRichTextBox>
<Controls:MyRichTextBox.ItemContainerStyle>
<Style TargetType="{x:Type Controls:MyTextElement}">
<!-- Whatever... -->
</Style>
</Controls:MyRichTextBox.ItemContainerStyle>
</Controls:MyRichTextBox>
这应该允许我为MyTextElement
中的MyRichTextBox
类型的所有元素定义样式。 方法1会给出相同的结果,但是两种方法都将失败,并出现相同的错误。
因为在不基于MyRichTextBox.ItemContainerStyle
情况下分配新样式有效,所以不清楚导致错误的原因是我做错了什么。
编辑 : MyTextElement
看起来像这样:
public class MyTextElement : Button
{
public MyTextElement() : base()
{
}
}
MyRichTextBox
有效逻辑结构如下所示:
<Controls:MyRichTextBox>
<FlowDocument>
<Paragraph>
<InlineUIContainer>
<Controls:MyTextElement Content="My Content"/>
</InlineUIContainer>
</Paragraph >
</FlowDocument>
</Controls:MyRichTextBox>
您只能将具有NewValue.TargetType
键的一个资源添加到ResourceDictionary
。
以下示例代码对我来说很好用:
public class MyTextElement : Run { }
public class MyRichTextBox : RichTextBox
{
public static DependencyProperty ItemContainerStyleProperty = DependencyProperty.Register("ItemContainerStyle", typeof(Style), typeof(MyRichTextBox), new FrameworkPropertyMetadata(default(Style), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnItemContainerStyleChanged));
public Style ItemContainerStyle
{
get
{
return (Style)GetValue(ItemContainerStyleProperty);
}
set
{
SetValue(ItemContainerStyleProperty, value);
}
}
static void OnItemContainerStyleChanged(DependencyObject Object, DependencyPropertyChangedEventArgs e)
{
(Object as MyRichTextBox).OnItemContainerStyleChanged((Style)e.OldValue, (Style)e.NewValue);
}
protected virtual void OnItemContainerStyleChanged(Style OldValue, Style NewValue)
{
//Make sure the old style is gone
if (OldValue != null)
Resources.Remove(OldValue.TargetType);
if (NewValue != null)
{
//This line does not attempt to utilize the specified style, but is stable
//Resources.Add(NewValue.TargetType, new Style(NewValue.TargetType));
//This line attempts to utilize the specified style, but is unstable
Resources.Add(NewValue.TargetType, new Style(NewValue.TargetType, NewValue));
}
}
}
<Controls:MyRichTextBox>
<Controls:MyRichTextBox.ItemContainerStyle>
<Style TargetType="{x:Type Controls:MyTextElement}">
<Setter Property="Foreground" Value="Red" />
</Style>
</Controls:MyRichTextBox.ItemContainerStyle>
<FlowDocument>
<Paragraph>
<Run Text="default" />
<Controls:MyTextElement Text="red" />
</Paragraph>
</FlowDocument>
</Controls:MyRichTextBox>
编辑:
MyTextElement
继承Button
并被分配为InlineUIContainer
的子InlineUIContainer
; 最终,样式需要应用于MyTextElement
,而不是Run
。 您的MyTextElement
继承Run
,不是任何子项
这也可以:
public class MyTextElement : Button
{
public MyTextElement() : base()
{
}
}
public class MyRichTextBox : RichTextBox
{
public static DependencyProperty ItemContainerStyleProperty = DependencyProperty.Register("ItemContainerStyle",
typeof(Style), typeof(MyRichTextBox), new FrameworkPropertyMetadata(default(Style),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnItemContainerStyleChanged));
public Style ItemContainerStyle
{
get
{
return (Style)GetValue(ItemContainerStyleProperty);
}
set
{
SetValue(ItemContainerStyleProperty, value);
}
}
static void OnItemContainerStyleChanged(DependencyObject Object, DependencyPropertyChangedEventArgs e)
{
(Object as MyRichTextBox).OnItemContainerStyleChanged((Style)e.OldValue, (Style)e.NewValue);
}
protected virtual void OnItemContainerStyleChanged(Style OldValue, Style NewValue)
{
//Make sure the old style is gone
if (OldValue != null)
Resources.Remove(OldValue.TargetType);
if (NewValue != null)
{
Resources.Add(NewValue.TargetType, new Style(NewValue.TargetType, NewValue));
}
}
}
<Controls:MyRichTextBox IsDocumentEnabled="True">
<Controls:MyRichTextBox.ItemContainerStyle>
<Style TargetType="{x:Type Controls:MyTextElement}">
<Setter Property="Foreground" Value="Red" />
</Style>
</Controls:MyRichTextBox.ItemContainerStyle>
<FlowDocument>
<Paragraph>
<InlineUIContainer>
<Controls:MyTextElement Content="My Content"/>
</InlineUIContainer>
</Paragraph >
</FlowDocument>
</Controls:MyRichTextBox>
注意我从OnItemContainerStyleChanged
方法中删除了以下行:
Resources.Add(NewValue.TargetType, new Style(NewValue.TargetType));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.