好的,這裏是處理:我有代碼在C#中工作,但是當我從PowerShell調用它時,它失敗。我無法弄清楚,但它是PowerShell特有的。下面是相關的代碼調用從C#庫(假設你已經添加的時間提前參考):序列化WPF數據模板和{綁定表達式}(來自PowerShell?)
public class Test {
[STAThread]
public static void Main()
{
Console.WriteLine( PoshWpf.XamlHelper.RoundTripXaml(
"<TextBlock Text=\"{Binding FullName}\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"/>"
));
}
}
編譯成可執行,工作正常...但如果你從PowerShell中,它調用該方法文本沒有返回{Binding FullName}
!
add-type -path .\PoshWpf.dll
[PoshWpf.Test]::Main()
我已經貼在庫中的全部代碼下面,都在PowerShell中添加型呼叫包裹起來,以便您可以只需將其粘貼到PowerShell的編譯(可以去掉第一個和最後一個行如果你想將它粘貼到一個新的控制檯應用程序在Visual Studio中
要輸出(從PowerShell 2)作爲可執行文件,只需將-OutputType參數更改爲ConsoleApplication,並將-OutputAssembly更改爲PoshWpf.exe(或其他) 。因此,您可以看到,從可執行文件運行SAME CODE可以爲您提供正確的輸出。
但運行上述兩行或從PowerShell手動調用[PoshWpf.XamlHelper]::RoundTripXaml
或[PoshWpf.XamlHelper]::ConvertToXaml
似乎根本沒有工作... 幫助?
Add-Type -TypeDefinition @"
using System;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace PoshWpf
{
public class Test {
[STAThread]
public static void Main()
{
Console.WriteLine( PoshWpf.XamlHelper.RoundTripXaml(
"<TextBlock Text=\"{Binding FullName}\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"/>"
));
}
}
public class BindingTypeDescriptionProvider : TypeDescriptionProvider
{
private static readonly TypeDescriptionProvider _DEFAULT_TYPE_PROVIDER = TypeDescriptor.GetProvider(typeof(Binding));
public BindingTypeDescriptionProvider() : base(_DEFAULT_TYPE_PROVIDER) { }
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
ICustomTypeDescriptor defaultDescriptor = base.GetTypeDescriptor(objectType, instance);
return instance == null ? defaultDescriptor : new BindingCustomTypeDescriptor(defaultDescriptor);
}
}
public class BindingCustomTypeDescriptor : CustomTypeDescriptor
{
public BindingCustomTypeDescriptor(ICustomTypeDescriptor parent) : base(parent) { }
public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
PropertyDescriptor pd;
var pdc = new PropertyDescriptorCollection(base.GetProperties(attributes).Cast<PropertyDescriptor>().ToArray());
if ((pd = pdc.Find("Source", false)) != null)
{
pdc.Add(TypeDescriptor.CreateProperty(typeof(Binding), pd, new Attribute[] { new DefaultValueAttribute("null") }));
pdc.Remove(pd);
}
return pdc;
}
}
public class BindingConverter : ExpressionConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return (destinationType == typeof(MarkupExtension)) ? true : false;
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(MarkupExtension))
{
var bindingExpression = value as BindingExpression;
if (bindingExpression == null) throw new Exception();
return bindingExpression.ParentBinding;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
public static class XamlHelper
{
static XamlHelper()
{
// this is absolutely vital:
TypeDescriptor.AddProvider(new BindingTypeDescriptionProvider(), typeof(Binding));
TypeDescriptor.AddAttributes(typeof(BindingExpression), new Attribute[] { new TypeConverterAttribute(typeof(BindingConverter)) });
}
public static string RoundTripXaml(string xaml)
{
return XamlWriter.Save(XamlReader.Parse(xaml));
}
public static string ConvertToXaml(object wpf)
{
return XamlWriter.Save(wpf);
}
}
}
"@ -language CSharpVersion3 -reference PresentationCore, PresentationFramework, WindowsBase -OutputType Library -OutputAssembly PoshWpf.dll
同樣,你可以得到由剛剛改變的最後一行,像這樣的可執行文件:
"@ -language CSharpVersion3 -reference PresentationCore, PresentationFramework, WindowsBase -OutputType ConsoleApplication -OutputAssembly PoshWpf.exe
順便提一下,現在我已經發布了,我注意到我沒有真正解釋這與DataTemplates有什麼關係:基本上,您必須生成XAML源以創建FrameworkTemplate任何類型 - 我試圖從已經創建的控件創建它們,所以我需要序列化回XAML來做到這一點。 – Jaykul 2010-03-21 05:47:32
不知道您的直接問題,但您不需要使用XAML在WPF中創建DataTemplate(儘管您使用Silverlight。)在WPF中,您可以使用FrameworkElementFactory對象的樹,這些對象的基本描述符包括元素類型,財產製定者,兒童等等。但這並不是那裏,也不是那裏。想想這個。 – Josh 2010-03-23 14:45:08
是的,我看了一下FrameworkElementFactory,但它有一點鈍,不推薦使用。我最關心的事情是相當簡單的模板,數據綁定僅限於像{Binding FullName}或{Binding Path = FullName}這樣的內容,如示例中所示 - 找到的代碼「有效」我真的喜歡使用它,並避免生成我自己的Xaml字符串;) – Jaykul 2010-03-24 06:38:00