Serializing WPF DataTemplates and {Binding Expressions} (from PowerShell?)

Ok, here's the deal: I have code that works in C #, but when I call it from PowerShell, it fails. I cannot understand this, but it is something specific to PowerShell. Here's the corresponding code calling the library (assuming you added the link ahead of time) from C #:

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\"/>"
      ) );
   }
}

Compiled into an executable that works fine ... but if you call this method from PowerShell, it returns without {Binding FullName}for text!

add-type -path .\PoshWpf.dll
[PoshWpf.Test]::Main()

I pasted below all the code for the library, all of this is completed in the AddSet PowerShell call, so you can just compile it by inserting it into PowerShell (you can leave the first and last lines if you want to paste it into a new console application in Visual Studio.

( PowerShell 2) -OutputType ConsoleApplication -OutputAssembly PoshWpf.exe( - ). , , SAME CODE .

, , [PoshWpf.XamlHelper]::RoundTripXaml [PoshWpf.XamlHelper]::ConvertToXaml PowerShell ... HELP?!

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
+3
3

( , ), , , PowerShell 3 - , , , PS3 .Net CLR 4 .

, System.Xaml -reference, PowerShell 3 4. , , , , ;)

+1

powershell, {} `? , powershell?

0

TypeConverter, XamlHelper. BindingConverter? {Binding}, WPF?

XAML, . MSDN XAML:

, , StaticResource Binding, . , XAML . , , . , , , URI . , ,

Given this, I'm not sure why this should actually work in a compiled application at all. But, as I said, I have to admit that I'm not sure what you are doing with TypeConverter, so maybe you have already addressed the above limitation.

0
source

Source: https://habr.com/ru/post/1737877/


All Articles