Заполните ListView настраиваемым списком файлов (FilePath и Size) в Powershell - PullRequest
0 голосов
/ 25 мая 2020

Я пытаюсь создать инструмент удаленного копирования, который отлично работает в консоли, но у меня возникают проблемы с созданием для него GUI.

Когда я заполняю свой Listbox списком файлов для копирования они просто не отображаются так, как задумано ...

Моя проблема в ChooseFiles функции

#xaml Code
$inputXML = @"
<Window x:Class="RemoteCopy.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:RemoteCopy"
        mc:Ignorable="d"
        Title="Remote Copy" Height="556.841" Width="800">
    <Grid>
        <Label Content="Remote Computer's IP:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
        <TextBox x:Name="RemoteIPTextbox" HorizontalAlignment="Left" Height="20" Margin="238,16,0,0" TextWrapping="Wrap" Text="IP address" VerticalAlignment="Top" Width="128"/>
        <Label Content="Username: " HorizontalAlignment="Left" Height="26" Margin="10,40,0,0" VerticalAlignment="Top" Width="131"/>
        <Label Content="Password: " HorizontalAlignment="Left" Height="26" Margin="10,70,0,0" VerticalAlignment="Top" Width="131"/>
        <TextBox x:Name="UsernameTextbox" HorizontalAlignment="Left" Height="20" Margin="238,46,0,0" TextWrapping="Wrap" Text="Username" VerticalAlignment="Top" Width="128"/>
        <Button x:Name="CheckConnectionButton" Content="Check Connection" HorizontalAlignment="Left" Margin="389,46,0,0" VerticalAlignment="Top" Width="107" Height="20"/>
        <Button x:Name="ChooseFilesButton" Content="Choose Files" HorizontalAlignment="Left" Height="80" Margin="535,16,0,0" VerticalAlignment="Top" Width="122"/>
        <ListView x:Name="FilesListView" HorizontalAlignment="Left" Height="234" Margin="33,128,0,0" VerticalAlignment="Top" Width="720">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="File"/>
                    <GridViewColumn Header="Size"/>
                </GridView>
            </ListView.View>
        </ListView>
        <Button x:Name="StartCopyButton" Content="Start Copy" HorizontalAlignment="Left" Height="24" Margin="33,374,0,0" VerticalAlignment="Top" Width="720"/>
        <ProgressBar x:Name="ProgressBar" HorizontalAlignment="Left" Height="20" Margin="113,418,0,0" VerticalAlignment="Top" Width="572"/>
        <Label Content="Progress:" HorizontalAlignment="Left" Height="28" Margin="33,418,0,0" VerticalAlignment="Top" Width="67"/>
        <Label Content="100%" HorizontalAlignment="Left" Height="28" Margin="714,418,0,0" VerticalAlignment="Top" Width="39"/>
        <PasswordBox x:Name="Passwordbox" HorizontalAlignment="Left" Margin="238,78,0,0" VerticalAlignment="Top" Width="128"/>
        <Button x:Name="ExitButton" Content="Exit" HorizontalAlignment="Left" Height="21" Margin="283,455,0,0" VerticalAlignment="Top" Width="213"/>

    </Grid>
</Window>

"@


$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^<Win.*', '<Window'
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[xml]$XAML = $inputXML
#Read XAML

$reader=(New-Object System.Xml.XmlNodeReader $xaml)
try{
    $Form=[Windows.Markup.XamlReader]::Load( $reader )
}
catch{
    Write-Warning "Unable to parse XML, with error: $($Error[0])`n Ensure that there are NO SelectionChanged or TextChanged properties in your textboxes (PowerShell cannot process them)"
    throw
}


#===========================================================================
# Load XAML Objects In PowerShell
#===========================================================================

$xaml.SelectNodes("//*[@Name]") | %{"trying item $($_.Name)";
    try {Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop}
    catch{throw}
    }


Function Get-FormVariables{
    if ($global:ReadmeDisplay -ne $true){Write-host "If you need to reference this display again, run Get-FormVariables" -ForegroundColor Yellow;$global:ReadmeDisplay=$true}
    write-host "Found the following interactable elements from our form" -ForegroundColor Cyan
    get-variable WPF*
    }

    Get-FormVariables


#===========================================================================
# Use this space to add code to the various form elements in your GUI
#===========================================================================


#my test folder
c:
Set-Location c:\temp

function DisplayInBytes($num) 
#reference: https://stackoverflow.com/questions/24616806/powershell-display-files-size-as-kb-mb-or-gb
{
    $suffix = "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
    $index = 0
    while ($num -gt 1kb) 
    {
        $num = $num / 1kb
        $index++
    } 
    "{0:N1} {1}" -f $num, $suffix[$index]
}


function ChooseFiles
{
    $WPFFilesListView.Clear()
    $filesToCopy = Get-Files
    $filesToCopy.FileNames | ForEach-Object {
        $currentfilesize = (Get-Item $_).Length
        $currentfilesize = DisplayInBytes -num $currentfilesize
        $row = New-Object System.Windows.Forms.ListViewItem($_)
        [void]$row.SubItems.Add("$currentfilesize")
        [void]$WPFFilesListView.Items.Add($row)
    }
}


Function Get-Files($initialDirectory="")
#Reference to https://stackoverflow.com/questions/15885132/file-folder-chooser-dialog-from-a-windows-batch-script
{
    [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")|Out-Null

    $myFile = new-object Windows.Forms.OpenFileDialog
    $myFile.InitialDirectory = Get-Location
    $myFile.Filter = "Text Files (*.txt)|*.txt|Powershell Script Files (*.ps1)|*.ps1|Batch Files (*.bat)|*.bat|All Files (*.*)|*.*"
    $myFile.ShowHelp = $true
    $myFile.Multiselect = $true
    [void]$myfile.ShowDialog()

    if ($myFile.Multiselect) { $myFile.FileNames } else { $myFile.FileName }
    return $myFile
}


$WPFExitButton.Add_Click({$form.close()})
$WPFChooseFilesButton.Add_Click({ChooseFiles})


$Form.ShowDialog() | out-null

Функция выбора моих файлов и заполнения моего списка - это функция :

function ChooseFiles
{
    $WPFFilesListView.Clear()
    $filesToCopy = Get-Files
    $filesToCopy.FileNames | ForEach-Object {
        $currentfilesize = (Get-Item $_).Length
        $currentfilesize = DisplayInBytes -num $currentfilesize
        $row = New-Object System.Windows.Forms.ListViewItem($_)
        [void]$row.SubItems.Add("$currentfilesize")
        [void]$WPFFilesListView.Items.Add($row)
    }
}

Но мой результат выглядит так: results

Я намеревался отобразить имя файла и размер файла, если я протестирую переменные, которые они работают

Write-host $_
write-host $currentfilesize

intended results

По одному в каждом столбце

1 Ответ

1 голос
/ 25 мая 2020

Вам нужно изменить две вещи, чтобы исправить отображение:

  1. Добавить DisplayMemberBinding в ListView

    <ListView x:Name="FilesListView" HorizontalAlignment="Left" Height="234" Margin="33,128,0,0" VerticalAlignment="Top" Width="720">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="File" DisplayMemberBinding="{Binding File}"/>
                <GridViewColumn Header="Size" DisplayMemberBinding="{Binding Size}"/>
            </GridView>
        </ListView.View>
    </ListView>
    
  2. Передать pscustomobject с указанными свойствами привязки к ListView

function ChooseFiles
{
  $WPFFilesListView.Clear()
  $filesToCopy = Get-Files
  $filesToCopy.FileNames | ForEach-Object {
    $currentfilesize = (Get-Item $_).Length
    $currentfilesize = DisplayInBytes -num $currentfilesize
    $WPFFilesListView.Items.Add([pscustomobject]@{File=$_;Size=$currentfilesize})
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...