【问题标题】:Error trying to implement IValueConverter in PowerShell - XAML GUI script尝试在 PowerShell 中实现 IValueConverter 时出错 - XAML GUI 脚本
【发布时间】:2019-06-29 09:55:38
【问题描述】:

我错过了什么?我试图为我的基于 XAML 的 PowerShell 脚本实现转换器,但没有运气。 我从 StackOverflow 等网站收集了一些信息。但在基于 powershell XAML 的 GUI 脚本中找不到一个成功的转换器实现。

在我正在测试转换器的代码中,它可以工作(您可以看到 2 个转换示例),这意味着 powershell 本身接受了新的转换器类型,购买此转换器无法在我的 xaml 代码中实现。

$src = @'
    using System;
    using System.Windows;
    using System.Windows.Data;
    using System.Globalization;

    namespace MyProject
    {

        public class DemoConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value == null)
                {
                    return "kuku";
                }
                else
                {            
                    return "bobo";
                }
            }
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {   
                return value;
            }
        }
    }
'@

Add-Type -AssemblyName PresentationFramework    
Add-Type -TypeDefinition $src -ReferencedAssemblies PresentationFramework

#Checking that the new type works and convert is done...
$c = new-object MyProject.DemoConverter
$c.Convert("gg", $null, $null, $null)
$c.Convert(55, $null, $null, $null)

#Now declaring and loading the xaml
[xml]$XAML = @'

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cnv="clr-namespace:MyProject" >
    <Window.Resources>
        <cnv:DemoConverter x:Key="TestConverter" />
    </Window.Resources>
    <Grid>     
        <TextBox x:Name="txtTestValue" Text="I'm here to show that xaml loading works!" />
    </Grid>
</Window>
'@

$reader=(New-Object System.Xml.XmlNodeReader $xaml) 

$Window=[Windows.Markup.XamlReader]::Load( $reader )

$Window.ShowDialog() | out-null

我不断收到此错误:

使用“1”参数调用“Load”的异常:“无法创建未知类型'{clr-namespace:MyProject}DemoConverter'。”

如果我删除该行:&lt;cnv:DemoConverter x:Key="TestConverter" /&gt; 它不会给出上述错误并且窗口将显示(但当然,xaml 中的转换将不可用),所以我想我在命名空间和/或 XAML 不喜欢的程序集减速方面做错了。

请注意,在我的 xaml 上,我还没有使用转换器。我只是想在尝试使用转换器之前克服上述错误。

非常感谢您!

【问题讨论】:

    标签: wpf powershell xaml ivalueconverter


    【解决方案1】:

    我注册 Stackoverflow 只是为了参与这个问题。

    在我在这里遇到这个问题之前,我搜索了 HOURS 以寻找解决方案,然后我的希望破灭了,看到它已经在这里搁置了将近一年而没有答案。

    我之前发现了这个相关的问题,它给出了我们试图用这个问题实现的基本解决方案,但没有提供任何让它真正起作用的细节。 How to use IValueConverter from powershell?

    幸运的是,经过几个小时,并拼凑了很多其他信息,我终于解决了!

    它有 3 块。

    1. 通过 C# 代码添加的转换器类型不属于表单的同一命名空间,即使您在 C# 类代码中指定了表单的命名空间。所以需要一个额外的 xmlns: 行来在表单中包含转换器类型的命名空间。然后在表单资源中定义转换器时,您引用该名称空间而不是表单自己的名称空间(通常是“本地”,但我看到您的示例使用了“cnv”)。此外,出于以下原因,您希望 C# 代码中的命名空间与表单自己的命名空间不同。 (我不确定,但系统可能会因为 2 个不同的命名空间而感到困惑,这些命名空间在物理上是完全分开的。)
    2. 但是,即使添加了 xmlns: 行以包含转换器的命名空间,表单仍然找不到它。这是因为,我发现,添加的转换器类型也被添加到不同的程序集中。显然,当使用“Add-Type -TypeDefinition”添加自定义类型时,PowerShell 会创建自己的内存程序集并将类型添加到其中。因此,在添加的 xmlns: 行中包含转换器的命名空间,我们还必须为自定义转换器类型指定程序集。
    3. 但是,但是...更糟糕的是,这个“编造”的程序集有一个随机生成的名称,并且每次运行脚本时该程序集名称都不同。 (我在任何地方都找不到这个事实。我完全是偶然发现的。)那么,如果您不知道程序集名称,如何包含该名称呢?基本上做你所做的,在变量中创建新转换器对象的实例,然后检查该新对象变量的属性以确定程序集名称。然后使用字符串 Replace 用程序集名称更新您的 XAML 字符串。

    所以,请参阅我发布的更新代码,其中包含以下更改。正如原始海报所指出的,此示例没有显示转换器的运行情况,但脚本至少会运行并无错误地显示表单,表明表单本身接受了转换器定义和 TextBox 中的用法。

    • 将 C# 代码中的命名空间更改为 MyConverter,因此它有所不同 来自表单的 MyProject 命名空间。
    • 在创建转换器对象的 $c 实例的行中,我将命名空间更改为 MyConverter 而不是 MyProject,以匹配上面的新命名空间。
    • 添加了 $AssemblyName 变量以提取随机程序集名称。 (我还注释掉了对 Convert 和 ConvertBack 的调用。)
    • 将 XAML 代码的 Here-String 更改为字符串变量 $inputXML,以便我们可以对其使用 Replace。稍后将转换为 xml 文档。
    • xlmns:Converter 行已添加以包含 MyConverter 命名空间。注意“;assembly=myassembly”部分。 “myassembly”名称只是字符串替换的占位符,以便以后轻松查找。
    • 在转换器 Window.Resources 的声明中,将“cnv:”更改为“Converter:”以匹配转换器类型的命名空间声明。
    • 添加了另一个 TextBox 以显示包括转换器并且表单构建接受它。
    • 添加了 [xml]$XAML = $inputXML.... 行以转换为 xml 并替换为实际的程序集名称。

    代码

    $src = @'
        using System;
        using System.Windows;
        using System.Windows.Data;
        using System.Globalization;
    
        namespace MyConverter
        {
    
            public class DemoConverter : IValueConverter
            {
                public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    if (value == null)
                    {
                        return "kuku";
                    }
                    else
                    {            
                        return "bobo";
                    }
                }
                public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
                {   
                    return value;
                }
            }
        }
    '@
    
    Add-Type -AssemblyName PresentationFramework    
    Add-Type -TypeDefinition $src -ReferencedAssemblies PresentationFramework
    
    #Checking that the new type works and convert is done...
    $c = new-object MyConverter.DemoConverter
    $AssemblyName = $c.gettype().Assembly.FullName.Split(',')[0]
    #$c.Convert("gg", $null, $null, $null)
    #$c.Convert(55, $null, $null, $null)
    
    #Now declaring and loading the xaml
    $inputXML = @'
    
    <Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Converter="clr-namespace:MyConverter;assembly=myassembly"
    xmlns:cnv="clr-namespace:MyProject" >
        <Window.Resources>
            <Converter:DemoConverter x:Key="TestConverter" />
        </Window.Resources>
        <Grid>     
            <TextBox x:Name="txtTestValue" Text="I'm here to show that xaml loading works!" />
            <TextBox x:Name="txtTestValue2" Text="{Binding Path=Whatever, Converter={StaticResource TestConverter}}" />
       </Grid>
    </Window>
    '@
    
    [xml]$XAML = $inputXML -replace 'myassembly', $AssemblyName
    
    $reader=(New-Object System.Xml.XmlNodeReader $xaml) 
    
    $Window=[Windows.Markup.XamlReader]::Load( $reader )
    
    $Window.ShowDialog() | out-null
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-04
      • 2020-10-07
      • 1970-01-01
      • 2019-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-30
      相关资源
      最近更新 更多