Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# PowerShell WPF应用程序中的动态数据模板_C#_Wpf_Powershell - Fatal编程技术网

C# PowerShell WPF应用程序中的动态数据模板

C# PowerShell WPF应用程序中的动态数据模板,c#,wpf,powershell,C#,Wpf,Powershell,我使用XAML和PowerShell创建了一个简单的WPF应用程序,它由一个TabControl组成,我希望在其子TabItems中显示多种数据。根据提供的数据类型,我希望TabControl的子TabItems使用不同的DataTemplate 我知道在我的情况下,最好(唯一?)的方法是在C#中创建一个自定义DataTemplateSelector类来处理模板选择 我尝试过这样做,但在使用自定义类时遇到了困难。以下是我得到的错误: Exception calling "Load" with "

我使用XAML和PowerShell创建了一个简单的WPF应用程序,它由一个TabControl组成,我希望在其子TabItems中显示多种数据。根据提供的数据类型,我希望TabControl的子TabItems使用不同的DataTemplate

我知道在我的情况下,最好(唯一?)的方法是在C#中创建一个自定义DataTemplateSelector类来处理模板选择

我尝试过这样做,但在使用自定义类时遇到了困难。以下是我得到的错误:

Exception calling "Load" with "1" argument(s): "Cannot create unknown type
'{clr-namespace:myNamespace}myDataTemplateSelector'."
At line:101 char:1
+ $Window = [Windows.Markup.XamlReader]::Load($Reader)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : XamlParseException
我怀疑我未正确加载所需的程序集或命名空间,因此无法访问自定义命名空间和自定义类。我以前从未使用过C#,因此我非常感谢您提供的任何帮助

一旦我解决了这个问题,我知道我的C#自定义类的内部逻辑将无法按预期工作,但这是一个单独的问题。C代码似乎是有效的,因为我可以独立运行它并实例化我的自定义类

如果删除所有与DataTemplateSelector相关的位并将以下内容添加到TabControl中,XAML和代码也可以正常工作:

ContentTemplate="{StaticResource UserDataTemplate}" ContentTemplate=“{StaticResource UserDataTemplate}” 下面是代码(包括C#、XAML、PowerShell):

$Assemblies=@(“系统”、“PresentationFramework”、“WindowsBase”、“System.Xaml,版本=4.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089”)
$cSharpSource=@”
使用制度;
使用System.Windows;
使用System.Windows.Controls;
名称空间myNamespace
{
公共类myDataTemplateSelector:DataTemplateSelector
{
公共数据模板UserDataTemplate
{get;set;}
公共数据模板GroupDataTemplate
{get;set;}
公共覆盖数据模板SelectTemplate(对象项,DependencyObject容器)
{   
如果(项目作为字符串==“用户”)
{
返回UserDataTemplate;
}
else if(项目作为字符串==“组”)
{
返回GroupDataTemplate;
}
其他的
{
返回null;
}
}
}
}
"@
添加类型-TypeDefinition$cSharpSource-ReferencedAssemblys$Assemblys
添加类型-AssemblyName PresentationFramework
[xml]$XAML=@”
"@
#解析XAML
$Reader=(新对象System.Xml.XmlNodeReader$XAML)
$Window=[Windows.Markup.XamlReader]::加载($Reader)
#迭代每个XAML节点,并为每个节点创建一个变量
$XAML.SelectNodes(“/*[@*[包含(翻译(名称(.),'n','n'),'name')]]”)ForEach对象{
新变量-Name$\ux.Name-Value$Window.FindName($\ux.Name)-Force
}
#示例数据
$UserTabItem=[PSCustomObject]@{
“ObjectClass”=“用户”
}
$GroupTabItem=[PSCustomObject]@{
“对象类”=“组”
}
#单击可将子TabItems添加到TabControl
$UserTabItem\按钮。添加\单击({
$TabControl.AddChild($UserTabItem)
})
$GroupTabItem\按钮。添加\单击({
$TabControl.AddChild($GroupTabItem)
})
$Window.ShowDialog()
我还探讨了将XAML DataTemplates存储为PowerShell变量,并在添加子项之前将TabControl的ContentTemplate属性设置为适当的DataTemplate。这是不成功的,在阅读了WPF的模板文档之后,这可能是不可能的


我对其他方法持开放态度。谢谢您的时间。

您需要指定程序集和命名空间。local=“clr namespace:myNamespace”只需指定名称空间。我不确定它在PS环境中是如何工作的


正如Slime recipe所建议的那样,首先在Visual Studio中创建控件库要轻松得多

我在Visual Studio中创建了一个新的“类库(.NET Framework)”项目,将现有语法有效的C#代码粘贴到解决方案中,添加对适当程序集的引用,并构建了该项目

我将生成的myDataTemplateSelector.dll文件复制到与PowerShell脚本文件相同的目录中

我加载了一个新的PowerShell控制台(重新使用控制台未正确加载程序集),并运行以下命令来测试DLL:

Add-Type -Path .\myDataTemplateSelector.dll
[myNamespace.myDataTemplateSelector]::New()
这成功地实例化了我的自定义类

最后,我更新了我的XAML:

xmlns:local="clr-namespace:myNamespace;assembly=myDataTemplateSelectorLibrary"
WPF应用程序现在运行

我希望其他答案能够解释如何在不必在Visual Studio中编译C#代码的情况下完成同样的任务,因为我不希望在这个项目中依赖非人类可读的文件(即DLL文件)

编辑-完全回答:

Slice recipe建议以编程方式查找程序集名称,而不是依赖于我假设的程序集名称(基于我的C#代码),这使我走上了正确的道路。再次感谢

在PowerShell中运行C#代码时,通常使用Add Type,它只将代码加载到内存中

如果指定源代码,“添加类型”将编译指定的源代码并生成包含新的.NET Framework类型的内存中程序集

为了访问添加代码的元数据,必须使用Add Type的-Passthru参数:

-穿越

返回表示已添加类型的System.Runtime对象。默认情况下,[添加类型]不生成任何输出

然后,我存储了修改后的Add Type命令的输出:

$Type = Add-Type -TypeDefinition $cSharpSource -ReferencedAssemblies $Assemblies -PassThru
然后将访问程序集的全名:

> $Type.Assembly.Fullname
m0m5m4la, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
第一个字符串“m0m5m4la”是所需的程序集名称,在添加类型时随机生成,并用作内存中程序集的引用

最后,可以在脚本运行并插入XAML时访问它:

...
$Type = Add-Type -TypeDefinition $cSharpSource -ReferencedAssemblies $Assemblies -PassThru
$AssemblyName = $Type.Assembly.Fullname.Split(",",2)[0] 

Add-Type -AssemblyName PresentationFramework

[xml]$XAML = @"
<Window x:Name="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="650" Width="300" FontSize="11"
    xmlns:local="clr-namespace:myNamespace;assembly=$($AssemblyName)">
...
。。。
$Type=添加类型-类型定义
...
$Type = Add-Type -TypeDefinition $cSharpSource -ReferencedAssemblies $Assemblies -PassThru
$AssemblyName = $Type.Assembly.Fullname.Split(",",2)[0] 

Add-Type -AssemblyName PresentationFramework

[xml]$XAML = @"
<Window x:Name="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="650" Width="300" FontSize="11"
    xmlns:local="clr-namespace:myNamespace;assembly=$($AssemblyName)">
...
xmlns:local="clr-namespace:$([YourClass].Namespace);assembly=$([YourClass].Assembly.FullName)"
<Window.Resources>
        <local:YourClass x:Key="_yclass" />
</Window.Resources>