使用简化语法在XAML中分配属性,而不使用转换器和标记扩展

时间:2013-04-29 09:23:45

标签: xaml

我有像这样的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 -->

我知道它看起来像是一个标记扩展,但为每个引入的效果编写一个单独的标记扩展名太繁琐了。看起来太基本了,没有解决方案:)

有什么建议吗?

提前致谢!

3 个答案:

答案 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()而不定义方法并期望它只是做什么你要。如果您只是想避免编写多个标记扩展,那么只需编写一个可以重用的扩展。如果你可以使用一个通用模式(默认构造函数,接收参数的常用方法)来制作不同的效果,那么你可以将一个类型和一些其他设置参数传递给标记扩展,并让它创建该类型的实例并设置参数对于你当前或未来的任何类型。