当我使用StaticResource作为参数时,我遇到了自己创建的自定义资源扩展的问题。 根据{{3}},这应该有效: “支持嵌套多个标记扩展,并且每个标记扩展将首先进行最深入的评估。” 事实上它确实在运行时工作。但在设计时我发现内部StaticResource扩展没有解决 - 而是将StaticResource扩展本身传递给自定义的MarkupExtension,它不起作用。
我已经减少到绝对最小值来证明问题:
1)创建新的WPF应用程序“TestApp”
2)创建新类TestExtension,它只是从ProvideValue()返回其参数:
using System;
using System.Windows.Markup;
namespace TestApp
{
public class TestExtension : MarkupExtension
{
public TestExtension(object param) { _originalValue = param; }
public override object ProvideValue(IServiceProvider serviceProvider) { return _originalValue; }
private object _originalValue;
}
}
3)将资源添加到主窗口并将其用作扩展名的参数:
<Window x:Class="TestApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:TestApp"
xmlns:sys="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<sys:Double x:Key="TestResource">99</sys:Double>
</ResourceDictionary>
</Window.Resources>
<Grid Background="Red" Width="{local:TestExtension {StaticResource TestResource}}" Height="99" />
</Window>
构建并运行并且它工作正常 - 但在设计器中,Grid的宽度是“Auto”而不是99,并且在编辑器中Width属性被误解为错误'System.Windows.StaticResourceExtension'不是属性'宽度'的有效值。
你可能认为你可以检测到这种情况并在传入的StaticResourceExtension中调用ProvideValue(),如下所示:
using System;
using System.Windows;
using System.Windows.Markup;
namespace WPFGUI.MarkupExtensions
{
public class TestExtension : MarkupExtension
{
public TestExtension(object param)
{
_originalValue = param;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_originalValue.GetType() == typeof(StaticResourceExtension))
{
_originalValue = (_originalValue as StaticResourceExtension).ProvideValue(serviceProvider);
throw new XamlParseException("This exception will not hit because the above line does not execute at design time.");
}
return _originalValue;
}
private object _originalValue;
}
}
......但这也不起作用。设计器在遇到对StaticResourceException的调用时停止运行TestExtension:ProvideValue():ProvideValue()。
答案 0 :(得分:0)
为了记录,我找到了一种方法:
public class TestExtension : MarkupExtension
{
public TestExtension(object param)
{
_param = param;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_param is StaticResourceExtension || _param is DynamicResourceExtension)
{
IProvideValueTarget pvt = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
object key = (_param as StaticResourceExtension)?.ResourceKey ?? (_param as DynamicResourceExtension)?.ResourceKey;
return (pvt.TargetObject as FrameworkElement)?.FindResource(key) ?? (pvt.TargetObject as FrameworkContentElement)?.FindResource(key);
}
return _param;
}
private object _param;
}