0

I am kinda' new to Powershell and have searched the ends of the earth for a solution, but I can't seem to find anything. I hope it's still doable.

I am trying to sort a CollectionView by date that's in string format. In my custom sorter, I want to convert the date strings (M/dd/yyyy) into Date objects and have the Comparer sort it by date. My CollectionView is filled like this:

$stuff = [System.Collections.ObjectModel.ObservableCollection[System.Object]](ImportClixml -Path $path)
$view = [System.Windows.Data.CollectionView]([System.Windows.Data.CollectionViewSource]::GetDefaultView($stuff))

The XML data is filled with Properties that are String and Boolean values. the Date value I am trying to sort is a String. The CollectionView is the bound to a DataGrid like so: $myDataGrid.ItemsSource = $myCollectionView Can I just make a function that sorts and just point to it somehow?

function customSorter{ #Do Stuff }
$myCollectionView.CustomSort = customSorter

The CustomSort property takes in a System.Collections.IComparer object. I'm not sure how to approach this. I would prefer to just keep it all in powershell 4 and not import C# code or something like that. Any help is appreciated.

1housand
  • 508
  • 7
  • 16
  • What contains "#Do Stuff"? It would be interesting to know what kind of process is done to fill the collectionView in order to help you – Manu Jun 06 '17 at 15:00
  • @ManuP Hi, I have edited my post with the way I fill my CollectionView. That #DoStuff was the function I was going to make in order to sort, if that is how it works. – 1housand Jun 06 '17 at 15:14

1 Answers1

0

You can format your string dates into a datetime object

For example, yyyy-MM-dd format will be easy to sort.

If you want to convert your string dates you can use :

$timeinfo = '6/06/2017'
$template = 'M/dd/yyyy'
$newDate = Get-Date([DateTime]::ParseExact($timeinfo, $template, $null)) -Format "yyyy-MM-dd"

Result is : 2017-06-06

Manu
  • 1,685
  • 11
  • 27
  • Thank you. I am going to use that solution for now, but do you by any chance know how to make a custom sorter? I wanted to call the sorter whenever an event was called and I wanted to sort the collection view. – 1housand Jun 06 '17 at 15:42
  • Do you have an example of the results you want? If you simply want to display an array of custom objects just use `$stuff = Import-CliXML -Path $Path` and sort `$stuff` by date (=properties?) when needed – Manu Jun 06 '17 at 15:48
  • The CollectionView is the ItemsSource of a DataGrid and I wanted to sort the Date column when it was clicked. I have the event function set up, just didn't know how to set `$myCollectionView.CustomSort = ?` With your solution, would I be doing that with the CollectionView? – 1housand Jun 06 '17 at 16:43
  • I presume you use a Datagrid in a WPF form, so sort can just be done by clicking on the header of the column, no need to use a "customsorter". `$stuff = Import-CliXML -Path $Path` and `$datagrid1.ItemsSource = $stuff` and use headers to sort. – Manu Jun 06 '17 at 17:18
  • If sort by clicking on headers does not work, set Datagrid with `AutoGenerateColumns = False` and set 2 columns in Datagrid (one for properties and the other for the boolean values) with appropriate databinding – Manu Jun 06 '17 at 17:24
  • It's not sorting correctly right now because it's sorting it as a `String`, but I guess i can use your solution reformat it correctly and then reformat is again when I export it. How would I use your solution in conjunction with the `Import-Clixml`? And you said I can just sort `$stuff` by date. I tried sorting by date like this `$view.SortDescriptions(New-Object System.ComponentModel.SortDescription "Date", $direction), but it just sorts it as a `String`. – 1housand Jun 06 '17 at 17:48
  • I resorted to using a "customsorter" because of a few reasons: I have to keep the date format "m/dd/yyyy" for exporting, I would have to loop through over 2k items to change the format for both importing and exporting, I want to use the built-in property. – 1housand Jun 06 '17 at 17:48
  • To keep date format but casting as a datetime object : `$newDate = Get-Date([DateTime]::ParseExact($timeinfo, $template, $null)) -Format "M/dd/yyyy"` – Manu Jun 06 '17 at 17:52
  • `$stuff = Import-CliXML -Path $Path | Select-Object @{n="Date";e={Get-Date([DateTime]::ParseExact($_.Date, "M/dd/yyyy", $null)) -Format "M/dd/yyyy"}},Value` – Manu Jun 06 '17 at 17:55
  • `$datagrid1.ItemsSource = $stuff` – Manu Jun 06 '17 at 17:57
  • I let you change `$_.Date` and `Value` in `Select-Object` because I don't know the name of your properties – Manu Jun 06 '17 at 17:58
  • When I do the `Select-Object` on the `Import-Clixml` and click on the column header, it still sorts it as a `String` so months that start with a `1` like `10`, `11`, or `12` are sorted as `1`, not as the whole number. Maybe I'll just give up and just reorder the whole `CollectionView` with a sort algorithm. – 1housand Jun 06 '17 at 18:26
  • Why not use a correct formatted date like `(yyyy-MM-dd)` in the datagrid and when you need to use a date in a function, you convert it like `(M/dd/yyyy)`. – Manu Jun 06 '17 at 19:23
  • I would have to convert each date when I `Import-Clixml` into a `DateTime` object for it to sort correctly because it doesn't sort correctly when it's a `String`. How would I do that along with other properties like `Title`, `Description`, and `Date`? – 1housand Jun 06 '17 at 19:41
  • Try `$stuff = Import-CliXML -Path $Path | Select-Object Title,Description,@{n="Date";e={Get-Date([DateTime]::ParseExact($_.Date, "M/dd/yyyy", $null)) -Format "yyyy-MM-dd"}}` – Manu Jun 06 '17 at 19:42
  • That works, but when I export it, it adds a bunch of weird values. Is there a way to add a temporary `DateTime` property to the object that doesn't get exported? – 1housand Jun 06 '17 at 20:07
  • What kind of weird values? – Manu Jun 06 '17 at 20:09
  • It added a `MS DateTime` property object with a bunch of properties. I guess I'll just have to try converting it back to a `String` when I export... – 1housand Jun 06 '17 at 20:11
  • is there a way to dynamically add the other non-date properties during the `Import-Clixml`? – 1housand Jun 06 '17 at 20:11
  • Is it possible to get an example of the Import-CliXML output? – Manu Jun 06 '17 at 20:14
  • no, i'm sorry, i meant that it displays fine in the `DataGrid`, but when I export it to xml, it displays with a bunch of weird values. – 1housand Jun 06 '17 at 20:14
  • When you export, use `Export-CliXML | Select-Object Title,Description,@{n="Date";e={Get-Date($_.Date) -Format "M/dd/yyyy"}}` – Manu Jun 06 '17 at 20:16
  • what do you mean Import-CliXML output? you mean the xml file contents? – 1housand Jun 06 '17 at 20:19
  • it has to be converted back to a string on `Export` – 1housand Jun 06 '17 at 20:20
  • `Export-CliXML | Select-Object Title,Description,@{n="Date";e={(Get-Date($_.Date) -Format "M/dd/yyyy").ToString()}}` – Manu Jun 06 '17 at 20:21
  • is there a way to dynamically include everything like `Title`, `Description`, and 'Date' instead of actually typing every property out? Like mayebe a `Foreach` that goes through all the properties and when it's the `Date` then it converts it? – 1housand Jun 06 '17 at 20:25
  • You can use `Export-CliXML -Path "xxx" | Select-Object -ExcludeProperty xxx` where `xxx` are all propeties you don't want to be exported but by this way, you can't redefine the Date property as we did before – Manu Jun 06 '17 at 20:29