我正在尝试在附加属性的内容上设置一个DynamicResource,但这是行不通的。想弄明白为什么,但我搞不懂。
基本上,我正在使用John提供的代码:Watermark / hint text / placeholder TextBox in WPF在文本框上实现一个水印,并按如下方式使用:
<TextBox Text="{Binding SomeProperty}">
<helper:WatermarkService.Watermark>
<TextBlock FontStyle="Italic" Text="{DynamicResource SomeResource}" />
</helper:WatermarkService.Watermark>
</TextBox>如果内部TextBlock位于WatermarkService.Watermark附加属性之外,它就可以正常工作。由于某种原因,SomeResource是空的。
我的资源被加载为so this.Resources.MergedDictionaries.Add(lastDictionary);,因为应用程序是本地化的,数据是从一个中心位置检索的。
附加属性上的控件是否与其“父级”共享相同的资源?这里怎么了?谢谢
发布于 2013-09-09 12:04:43
问题很明显。通过向上解析逻辑树来解析动态资源。没有找到动态资源,因为textblock不在正确的逻辑树中,可能他没有逻辑父级,这就是找不到资源的原因。
您可以通过将它添加到正确的逻辑树中来解决这个问题,例如,它可能是textbox的子节点。它并不是那么简单,也取决于所需的用法,因为对逻辑树的定制并不是那么简单。
没有什么比拥有一个公共方法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();
}
}
}记住,这只是一个解决办法,这种方法只适用于动态资源的自定义文本框。
而且,它不是正确的实现,因为您应该将水印添加到其他逻辑子逻辑中,而不是忽略其他逻辑子节点,并且只有水印,而水印甚至没有像下面这样检查空值:
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扩展功能,但对于任何控件来说,它都不是可扩展的解决方案。
https://stackoverflow.com/questions/18697209
复制相似问题