0

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

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

有什么建议么?

提前致谢!

4

3 回答 3

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}.

于 2013-06-10T13:43:23.290 回答
0

如果您只需要知道要创建的对象的类型,可以使用现有的Type标记扩展:

Effect="{x:Type thirdParty:Smoothing}"

或者,如果您需要对象的实例(这是您现有的标记正在创建的),您可以使用与转换器使用的方法类似的方法 - 即,将效果创建为资源,并按名称引用它:

<Window.Resources>
     <thirdParty:Smoothing x:Key="myEffect" />
</Window.Resources>
....
<ml:Visualizer Effect="{StaticResource myEffect}" />
于 2013-04-29T09:34:03.517 回答
0

您尝试实现的语法是为自定义标记扩展定义的语法,因此要求在没有定义的情况下执行此操作相当于要求MyNonexistentMethod()在 C# 中调用而不定义方法并期望它只执行您想要的操作。如果您只是想避免编写多个标记扩展,那么只需编写一个可以重复使用的。如果您可以使您的不同效果遵循通用模式(默认构造函数,接收参数的通用方式),那么您只需将类型和其他一些设置参数传递给您的标记扩展,并让它创建该类型的实例并设置参数为您提供任何当前或未来的类型。

于 2013-04-30T14:25:03.553 回答