问题很清楚。通过向上解析逻辑树来解析动态资源。找不到动态资源,因为您的文本块不在正确的逻辑树中,可能他没有逻辑父级,这就是找不到资源的原因。
您可以通过将其添加到正确的逻辑树来解决它,例如它可能是文本框的子级。它不是那么微不足道,并且还取决于所需的用法,因为逻辑树的定制并不是那么微不足道。
没有像拥有一个公共方法 AddLogicalChild 这样简单,因为那样你会搞砸整个系统。现在的问题是谁有责任这样做。一般的解决方案可能是有一个自定义 TextBox 覆盖逻辑子相关方法并返回水印文本块。
这不是全局解决方案,但在您的情况下,您可以有一个自定义文本框来覆盖 LogicalChildren 属性,如下所示:
public class WaterTextBox : TextBox
{
protected override IEnumerator LogicalChildren
{
get
{
ArrayList list = new ArrayList();
list.Add(WatermarkService.GetWatermark(this));
return (IEnumerator)list.GetEnumerator();
}
}
}
请记住,这只是一种解决方法,这种方法仅适用于具有动态资源的自定义文本框。
这也不是正确的实现,因为您应该将水印添加到其他逻辑子代,而不是忽略其他逻辑子代,并且只有水印甚至没有像这样检查 null:
public class WaterTextBox : TextBox
{
protected override IEnumerator LogicalChildren
{
get
{
ArrayList list = new ArrayList();
IEnumerator enumerator = base.LogicalChildren;
while (enumerator.MoveNext())
{
list.Add(enumerator.Current);
}
object watermark = WatermarkService.GetWatermark(this);
if (watermark != null && !list.Contains(watermark))
{
list.Add(WatermarkService.GetWatermark(this));
}
return (IEnumerator)list.GetEnumerator();
}
}
}
为了使其更通用,您应该定义一个类似 IWatermark 的接口,定义一个类似 IsWaterMarkAdded 的属性,该属性将由您的自定义 TextBox 和 ComboBox 实现,并将由水印服务使用。LogicalChildren 覆盖将检查此属性的值。这样,您可以扩展 TextBox 和 ComboBox 的功能,但它仍然不是任何控件的可扩展解决方案。