Powershell-INotifyPropertyChanged是否可以本机实现



有人知道INotifyPropertyChanged接口是否可以在Powershell中的对象上以本机方式实现,而无需构建C#类并使用Add-Type生成新的.NET程序集吗?

我在谷歌上搜索了我能想到的一切,但一直没能找到解决方案。

谢谢。

我正在尝试使用Powershell加载我的WPF原型,并面临同样的情况,到目前为止,我发现解决方案非常简单,它包括向Powershell类添加接口方法,最后要处理的是CanExecuteChanged事件,通过异常消息,它说没有找到add_CanExecuteChanged方法,解决方案是简单地将事件加法器和除法器相加,例如

class Relay: System.Windows.Input.ICommand {
[Action[object]]$command;

Relay([Action[object]]$Command){
$this.command = $Command;
}
[void]add_CanExecuteChanged ([System.EventHandler]$handler){}
[void]remove_CanExecuteChanged ([System.EventHandler]$handler){}
[bool]CanExecute([object]$arg) {return  $true; }
[void]Execute ([object]$arg){ $this.command?.Invoke($arg); }
}

对于INotifyPropertyChanged,情况有所不同,因为它需要getter和setter,以及对setter上PropertyChanged处理程序的调用,powershell中的属性可以作为C#中的字段来实现,后台powershell添加get_*和set_,在dotnet中添加get_生成的IL中的属性时就是这样,set_*方法,表示getter和setter,例如:

class Demo {
[string]$MyProperty;
}

如果你在结果中对一个实例执行GetMember-Force,你会发现(Get_MyProperty,set_MyProperty)方法,但当我尝试这样做时"例如像在java中一样;这些方法不会执行,但我尝试了在没有这些方法的情况下进行绑定,结果很好,以下是我的实验要点,绑定以双向模式工作:

https://gist.github.com/mouadcherkaoui/7b0f32d9dbefa71102acdbb07299c9bb

这是我修改的源代码,它本身包含了很多好的脚本:

https://github.com/SammyKrosoft/PowerShell/blob/master/How-To-Load-WPF-From-XAML.ps1

谨致问候。

否。将PowerShell视为CLIconsumer语言,而不是producer语言。也就是说,您可以构造和使用大多数.NET类型。然而,PowerShell本身并没有提供创建新.NET类型的工具,更不用说实现接口的类型了。虽然您可以在PowerShell中创建自定义对象,并使用技巧为这些对象提供PowerShell能够理解的类型名称,但这些技巧不适用于像WPF这样的.NET库。

这里有一个使用本机.NET事件的类。它派生自PSCustomObject并实现INotifyPropertyChanged接口。

我还添加了一个带有ObservableCollection和WPFDataGrid控件的用例。控件将能够通过add_PropertyChangedremove_...方法注册其事件处理程序,因此来自代码隐藏的属性更改将反映在UI中。

class MyNode : PSCustomObject, System.ComponentModel.INotifyPropertyChanged
{
hidden [string]$Nickname
[System.Collections.ArrayList]$PropertyChanged = @()

add_PropertyChanged([System.ComponentModel.PropertyChangedEventHandler]$handler)
{
$this.psobject.PropertyChanged.Add($handler)
}
remove_PropertyChanged([System.ComponentModel.PropertyChangedEventHandler]$handler)
{
$this.psobject.PropertyChanged.Remove($handler)
}
RaisePropertyChanged([string]$propname)
{
if ($this.psobject.PropertyChanged)
{
$evargs = [System.ComponentModel.PropertyChangedEventArgs]::new($propname)
$this.psobject.PropertyChanged.Invoke($this, $evargs) # invokes every member
}
}
MyNode()
{
$this | Add-Member -Name Nickname -MemberType ScriptProperty -Value {
return $this.psobject.Nickname
} -SecondValue {
param($value)
$this.psobject.Nickname = $value
$this.psobject.RaisePropertyChanged('Nickname')
}
}
}

DataGrid控件的代码隐藏:

$items = New-Object System.Collections.ObjectModel.ObservableCollection[MyNode]
$item = [MyNode]::new()
$item.psobject.add_PropertyChanged({
param($sender, $evargs)
write-host 'changed' $evargs.PropertyName
})
$items.Add($item)
$WPFdataGrid.ItemsSource = $items

数据网格的Xaml:

<DataGrid x:Name="dataGrid" AutoGenerateColumns="False" ItemsSource="{Binding}">
<DataGrid.Columns>
<DataGridTextColumn Header="Nickname" Binding="{Binding Nickname, Mode=TwoWay}" Width="160">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>

该代码适用于Windows7版本5.1。

最新更新