I have a GridView inside a ListView in a WPF application. Upon clicking the column header the list items get sorted alphabetically.
XAML:
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="200">
<GridViewColumn.HeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="cal:Message.Attach" Value="[Event Click]=[Action Sort($dataContext, 'Name')]"/>
</Style>
</GridViewColumn.HeaderContainerStyle>
</GridViewColumn>
And here's the sorting method in my ViewModel:
public void Sort(ShellViewModel dataContext, string propertyName)
{
// sorting logic
}
That works perfectly fine. But instead of passing 'Name' (or whatever the header is called), I'd like that to be a property.
I've tried Value="[Event Click]=[Action Sort($dataContext, $eventArgs.PropertyName)]" but that doesn't work and returns null.
You might want to consider changing the listview to a datagrid.
A datagrid has column click sorting built in. No code would be necessary. You'd need to change your markup to a datagrid, which might be non trivial of course. There may be some reason to pick listview instead of datagrid.
If that doesn't suit then the current approach looks like it is going to be tricky.
Looking at the msdn article about sorting a listview. That handles the event. The piece of code finding the propertyname is:
You might be able to get the binding from $eventArgs. if you use enough dots.
However, I think you would need to get the path out the binding in code.
I personally wouldn't be so keen on a viewmodel doing that sort of manipulation.
I'd suggest a behaviour if you want to encapsulate it or "just" do the sorting entirely in the view. Very much like
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/how-to-sort-a-gridview-column-when-a-header-is-clicked?view=netframeworkdesktop-4.8
Maybe you don't want the up down arrows and some other aspects.
If the viewmodel needs to know what the user picked you could add an attached property and bind that to the viewmodel. Setcurrentvalue on that property in the view.
Similarly, you could make that twoway. Handle change of the dependency property and set sort if the viewmodel needs to initially set sort dynamically.
Alternatively, extend the attached property concept. Put a sort togglebutton in the headers and bind to an observabledictionary. One entry per column. Handle property changed in the value of the observabledictionary and apply sort.