我将拖放操作限制为Powershell中的WPF列表框控件,只允许删除文本文件。我想使用System.Windows.DragDropEffects属性来阻止对DragEnter事件的放置操作,因为它还会更改鼠标光标,为拒绝放置操作提供用户反馈。我仍然可以通过验证Drop事件上的文件扩展名来限制对已删除文件所采取的操作。但我更愿意阻止掉落动作,以便更顺畅地进行用户交互。
在调试中我已经验证正确设置了DragDropEffect属性,但是事件处理程序似乎没有反映出更改。我相信尝试使用DragEventArgs类通过Powershell管道监视事件可能是一种限制。
WPF列表框的代码DragEnter事件如下所示。我注意到在$ _管道中传递的对象是System.Windows.DragEventArgs类。
$listbox.Add_DragEnter({
if ($_.Data.GetDataPresent([Windows.Forms.DataFormats]::FileDrop)) {
foreach ($filename in $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)) {
if(([System.IO.Path]::GetExtension($filename).ToUpper() -eq ".TXT")) {
$_.Effects = [System.Windows.DragDropEffects]::All
Write-Host 'Dropfile is a .TXT'
}
else {
$_.Effects = [System.Windows.DragDropEffects]::None
Write-Host 'Dropfile is NOT a .TXT'
}
}
}
})
使用WinForms列表框设置DragDropEffect属性按预期工作。鼠标更改并阻止丢弃事件。但是在这里,$ _管道传递的对象是System.Windows.Forms.DragEventArgs类。
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object Windows.Forms.Form
$listbox = New-Object Windows.Forms.ListBox
$listbox.AllowDrop = $true
$listbox.Add_DragEnter({
$_.Effect = [Windows.Forms.DragDropEffects]::None
})
$form.Controls.Add($listbox)
$form.ShowDialog()
WPF下面的完整测试代码:
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
[xml]$xaml = @'
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Remote Execution Toolkit" Height="300" Width="300">
<Grid>
<ListBox x:Name="listBox" AllowDrop="True" Height="250" HorizontalAlignment="Center" Width="250">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected}">
<TextBlock Text="{Binding}" TextAlignment="Left" Width="Auto" />
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
'@
# Load XAML Reader
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$Window=[Windows.Markup.XamlReader]::Load( $reader )
# Map XAML Controls
$xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | ForEach {
New-Variable -Name $_.Name -Value $Window.FindName($_.Name) -Force
}
# Drag Event to validate file extensions for drop effect
$listbox.Add_DragEnter({
if ($_.Data.GetDataPresent([Windows.Forms.DataFormats]::FileDrop)) {
foreach ($filename in $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)) {
if(([System.IO.Path]::GetExtension($filename).ToUpper() -eq ".TXT")) {
$_.Effects = [System.Windows.DragDropEffects]::All
Write-Host 'Dropfile is a .TXT'
}
else {
$_.Effects = [System.Windows.DragDropEffects]::None
Write-Host 'Dropfile is NOT a .TXT'
}
}
}
})
$Window.ShowDialog()
任何想法或建议表示赞赏!!
答案 0 :(得分:0)
经过大量的Google-Foo,运行Snoop WPF监控事件以及反复试验,我意识到我只是订阅了错误的Drag事件。要实现连续显示不允许游标操作的结果,必须使用DragOver事件。
$listbox.Add_DragOver({
...
$_.Effects = [System.Windows.DragDropEffects]::None
...
})
显然,在Powershell中使用WPF代码时,DragEnter事件仅在允许光标改回时触发,而DragOver事件在鼠标悬停在控件上时持续触发,保持显示操作不允许光标。
希望能够在一段时间内保存其他开发人员。
答案 1 :(得分:0)
通过在更改 $_.Handled = $true
后添加 $_.Effects
对我有用。
这是取自此处:https://stackoverflow.com/a/44321363/8262102
# Drag and drop UI example to a list box.
Add-Type -AssemblyName PresentationFramework, System.Drawing, System.Windows.Forms, WindowsFormsIntegration
[xml]$xaml = @'
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test Drop Form" Height="300" Width="500">
<Grid>
<ListBox x:Name="listBox" AllowDrop="True" Height="250" HorizontalAlignment="Center" Width="475">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected}">
<TextBlock Text="{Binding}" TextAlignment="Left" Width="Auto" />
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
'@
# Load XAML Reader
$reader = New-Object System.Xml.XmlNodeReader $xaml
$Form = [Windows.Markup.XamlReader]::Load($reader)
# Map XAML Controls
$formNamedNodes = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | Sort
$formNamedNodes | ForEach-Object {
Set-Variable -Name $_.Name -Value $Form.FindName($_.Name) # Set the variable names to the same as that of the controls.
}
# Drop event to add the files to the list box.
$listbox.Add_Drop({
if ($_.Data.GetDataPresent([Windows.Forms.DataFormats]::FileDrop)) {
foreach ($filename in $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)) {
if (([System.IO.Path]::GetExtension($filename).ToUpper() -eq ".TXT")) {
Write-Host "Dropped file extension: $filename is .TXT"
$listBox.Items.Add($filename)
}
else {
Write-Host "Dropped file extension: $filename is NOT .TXT"
}
}
}
})
# The DragOver event is there to handle changing the dropped effects.
$listbox.Add_DragOver({
if ($_.Data.GetDataPresent([Windows.Forms.DataFormats]::FileDrop)) {
foreach ($filename in $_.Data.GetData([Windows.Forms.DataFormats]::FileDrop)) {
if (([System.IO.Path]::GetExtension($filename).ToUpper() -eq ".TXT")) {
$_.Effects = [System.Windows.DragDropEffects]::All
Write-Host "$filename is a .TXT"
}
else {
$_.Effects = [System.Windows.DragDropEffects]::None
Write-Host "$filename is NOT a .TXT"
}
$_.Handled = $true # This is there to handle the effect. This needs to be below $_.Effect.
}
}
})
$Form.WindowStartupLocation = "CenterScreen"
$Form.ShowDialog()