附加属性和动态资源

本文关键字:动态 资源 属性 | 更新日期: 2023-09-27 18:30:36

我正在尝试在附加属性的内容上设置动态资源,但这不起作用。试图理解为什么,但我无法弄清楚。

基本上,我正在使用以下代码在文本框上实现水印:水印/提示文本/占位符 WPF 中的文本框 由John Myczek提供并按如下方式使用它:

<TextBox Text="{Binding SomeProperty}">
     <helper:WatermarkService.Watermark>
          <TextBlock FontStyle="Italic" Text="{DynamicResource SomeResource}" />
     </helper:WatermarkService.Watermark>
</TextBox>

如果内部TextBlock位于WatermarkService.Watermark附加属性之外,则工作正常。由于某种原因,SomeResource为空。

我的资源正在加载,因为应用程序已本地化并且数据是从中心位置检索的,因此this.Resources.MergedDictionaries.Add(lastDictionary);加载。

附加属性上的控件是否共享与其"父属性"相同的资源集?这是怎么回事?谢谢

附加属性和动态资源

问题很明显。动态资源是通过向上解析逻辑树来解决的。找不到动态资源,因为您的文本块不在正确的逻辑树中,可能他没有逻辑父级,这就是找不到资源的原因。

您可以通过将其添加到正确的逻辑树来解决它,例如它可以是文本框的子级。它不是那么简单,还取决于所需的用法,因为逻辑树的自定义不是那么简单。

没有像拥有公共方法AddLogicalChild那么简单,因为那样你会搞砸整个系统。现在的问题是,谁有责任这样做。常规解决方案可能是使用一个自定义文本框,该文本框覆盖与逻辑子项相关的方法,并返回水印文本块。

它不是全局解决方案,但在您的情况下,您可以使用一个自定义文本框覆盖 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,定义一个属性,如 IsWaterMarkAdd,该属性将由自定义文本框和组合框实现,并由水印服务使用。逻辑子项覆盖将检查此属性的值。这样,您可以扩展文本框和组合框的功能,但它仍然不是任何控件的可扩展解决方案。