我有像这样的XAML
<ml:Visualizer Smooth="True" />
最近我们添加了不同类型的预处理,例如平滑,模糊,锐化等 现在我们像这样写
<ml:Visualizer>
<ml:Visualizer.Effect>
<thirdParty:Smoothing/>
</ml:Visualizer.Effect>
</ml:Visualizer>
是否可以将属性指定为XML属性,但可能无需编写自定义类型转换器或MarkupExtensions。目标是使用简短的语法来分配属性,但实际效果可以稍后由第三方作为DLL提供,我们需要在XAML中引用它们。
<ml:Visualizer Effect="{thirdParty:Smoothing}" /> <!-- BUT WITH NO CUSTOM MARKUP EXTENSION -->
如果确实可能,那么下一个级别就是设置效果的属性(即使只有一个默认构造函数可用)。
<ml:Visualizer Effect="{thirdParty:Smoothing Factor=5}" /> <!-- BUT WITH NO CUSTOM MARKUP EXTENSION -->
我知道它看起来像是一个标记扩展,但为每个引入的效果编写一个单独的标记扩展名太繁琐了。看起来太基本了,没有解决方案:)
有什么建议吗?
提前致谢!
答案 0 :(得分:2)
可以在没有任何标记扩展的情况下完成。
语法为SomeProp="{YourClass}"
或SomeProp="{YourClass Prop=Value}"
为SomeProp指定一个YourClass实例。
一个例子(在.Net 4.0上验证):
<!-- Works with no markup extensions HardDriveExtension in the code! -->
<Computer Storage="{HardDrive Gigabytes=2.5}"
xmlns="clr-namespace:XamlExperiments;assembly=XamlExperiments"
/>
using System.IO;
using System.Xaml;
using System;
namespace XamlExperiments
{
class Program
{
static void Main(string[] args)
{
var xamlText =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<Computer Storage=""{HardDrive Gigabytes=2.5}""
xmlns=""clr-namespace:XamlExperiments;assembly=XamlExperiments""
/>
";
var computer = (Computer)XamlServices.Load(new StringReader(xamlText));
computer.Process();
}
}
public class Computer
{
public IStorage Storage { get; set; }
public void Process() { Storage.Store();}
}
public interface IStorage
{
void Store();
}
public class HardDrive : IStorage
{
public double Gigabytes { get; set; }
public void Store() {Console.WriteLine("Stored 1GB on HardDrive");}
}
}
输出是:
Stored 1GB on HardDrive
请注意没有任何扩展标记,您可以使用简单{HardDrive Gigabytes=2.5}
实例化HardDrive实例。
答案 1 :(得分:0)
如果您只需要知道要创建的对象类型,则可以使用现有的Type
标记扩展名:
Effect="{x:Type thirdParty:Smoothing}"
或者,如果您需要对象的实例(这是您现有的标记正在创建的实例),您可以使用与转换器使用的方法类似的方法 - 即,将效果创建为资源,并引用它按名称:
<Window.Resources>
<thirdParty:Smoothing x:Key="myEffect" />
</Window.Resources>
....
<ml:Visualizer Effect="{StaticResource myEffect}" />
答案 2 :(得分:0)
您尝试实现的语法是为自定义标记扩展定义的语法,因此要求在没有自定义标记扩展的情况下执行此操作等同于要求在C#中调用MyNonexistentMethod()
而不定义方法并期望它只是做什么你要。如果您只是想避免编写多个标记扩展,那么只需编写一个可以重用的扩展。如果你可以使用一个通用模式(默认构造函数,接收参数的常用方法)来制作不同的效果,那么你可以将一个类型和一些其他设置参数传递给标记扩展,并让它创建该类型的实例并设置参数对于你当前或未来的任何类型。