Reputation: 2373
I have a XAML like this
<ml:Visualizer Smooth="True" />
Recently we have added different types of preprocessing, like e.g. Smoothing, Bluring, Sharpening, etc. Now we write it like this
<ml:Visualizer>
<ml:Visualizer.Effect>
<thirdParty:Smoothing/>
</ml:Visualizer.Effect>
</ml:Visualizer>
Is it possible to assign a property as an XML attribute but perhaps without writing custom type converters or MarkupExtensions. The goal is to have a short syntax for assigning the property however the actual effects can be later provided by a third party as a DLL and we need to reference them in XAML.
<ml:Visualizer Effect="{thirdParty:Smoothing}" /> <!-- BUT WITH NO CUSTOM MARKUP EXTENSION -->
And if it is possible indeed, then the next level would be to set properties of effects (even if there is only a default constructor available).
<ml:Visualizer Effect="{thirdParty:Smoothing Factor=5}" /> <!-- BUT WITH NO CUSTOM MARKUP EXTENSION -->
I know it looks as a markup extension but it would be too tedious to write a separate markup extension for each effect introduced. Looks as a too basic thing to have no solution for that :)
Any suggestions?
Thanks in advance!
Upvotes: 0
Views: 173
Reputation: 2373
It's possible to do it without any markup extensions at all.
The syntax is SomeProp="{YourClass}"
or SomeProp="{YourClass Prop=Value}"
assigns SomeProp with an instance of YourClass.
An example (verified on .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");}
}
}
Output is:
Stored 1GB on HardDrive
Note that without any markup extension you can instantiate an instance of HardDrive with just simple {HardDrive Gigabytes=2.5}
.
Upvotes: 2
Reputation: 24453
The syntax you're trying to achieve is the syntax defined for custom markup extensions so asking to do that without one is equivalent to asking to call MyNonexistentMethod()
in C# without defining the method and expecting it to just do what you want. If you're just trying to avoid writing multiple markup extensions, then just write one that you can reuse. If you can make your different effects follow a common pattern (default constructors, common way to receive parameters) then you can just pass in a type and some other setting arguments to your markup extension and let it create an instance of that type and set parameters for you on any current or future type.
Upvotes: 0
Reputation: 34218
If you just need to know the type of object to create, you can use the existing Type
markup extension:
Effect="{x:Type thirdParty:Smoothing}"
Or, if you need an instance of the object (which is what your existing markup is creating), you could use a similar method to that used by converters - that is, create the effects as a resource, and refer to it by name:
<Window.Resources>
<thirdParty:Smoothing x:Key="myEffect" />
</Window.Resources>
....
<ml:Visualizer Effect="{StaticResource myEffect}" />
Upvotes: 0