Я написал функцию для сортировки ListView при щелчке по заголовку столбца. Теперь я хочу, чтобы функция работала для любого столбца. Моей первой мыслью было передать строку, представляющую свойство, отображаемое в столбце и использующее if
или switch
для сортировки по правильному свойству, например:
private bool sortOrder = false;
public void SortCol(string property)
{
OUModel ou = ADRoot.Descendants().Where(node => node.IsSelected == true).FirstOrDefault() as OUModel;
if (ou != null)
{
switch (property)
{
case "Name":
if (sortOrder)
{
ou.Computers = new List<RemoteComputer>(ou.Computers.OrderBy(c => c.Name));
}
else
{
ou.Computers = new List<RemoteComputer>(ou.Computers.OrderByDescending(c => c.Name));
}
break;
case "LastUpdated":
if (sortOrder)
{
ou.Computers = new List<RemoteComputer>(ou.Computers.OrderBy(c => c.LastUpdated));
}
else
{
ou.Computers = new List<RemoteComputer>(ou.Computers.OrderByDescending(c => c.LastUpdated));
}
break;
// etc...
}
sortOrder = !sortOrder;
}
}
Но это, очевидно, будет довольно длинным и повторяющийся. Вместо этого я задавался вопросом, мог ли бы я передать собственность непосредственно. Но я пытаюсь передать тип свойства из XAML (используя Caliburn.Micro Actions) и не могу понять, как.
private bool sortOrder = false;
public void SortCol<T>(Func<RemoteComputer, T> property)
{
OUModel ou = ADRoot.Descendants().Where(node => node.IsSelected == true).FirstOrDefault() as OUModel;
if (ou != null)
{
if (sortOrder)
{
ou.Computers = new List<RemoteComputer>(ou.Computers.OrderBy(property));
}
else
{
ou.Computers = new List<RemoteComputer>(ou.Computers.OrderByDescending(property));
}
sortOrder = !sortOrder;
}
}
XAML:
<!-- Name Spaces
xmlns:models="clr-namespace:MyProject.Models"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cal="http://www.caliburnproject.org"
-->
<!-- TreeView the ListView is bound to -->
<TreeView x:Name="ADTree" ItemsSource="{Binding ADRoot.Children}">
<!-- -->
<ListView x:Name="ADComputers" ItemsSource="{Binding SelectedItem.Computers, ElementName=ADTree, Mode=TwoWay}" SelectionMode="Multiple" ItemContainerStyle="{DynamicResource RemoteComputerItem}">
<ListView.View>
<GridView>
<GridViewColumn x:Name="Name" Width="120" DisplayMemberBinding="{Binding Name}">
<GridViewColumn.Header>
<GridViewColumnHeader x:Name="SortName" Content="Computer Name">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="SortCol">
<!-- Trying to pass type here, but nested types are not supported. Don't know how else I can do this -->
<cal:Parameter Value="{x:Type models:RemoteComputer.Name}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</GridViewColumnHeader>
</GridViewColumn.Header>
</GridViewColumn>
<!-- Other Columns -->
</GridView>
</ListView.View>
</ListView>
Классы et c:
class ADTreeViewModel : OUModel
{
public OUModel ADRoot { get; set; } = new OUModel(null, false); // <<< TreeView is bound to this, and ListView is bound to TreeView.SelectedItem.Computers
}
class OUModel : PropertyChangedBase, ITreeViewItemViewModel
{
private List<RemoteComputer> computers = new List<RemoteComputer>();
public List<RemoteComputer> Computers { get { return computers; } set { computers = value; NotifyOfPropertyChange(); } }
}
class RemoteComputer : PropertyChangedBase
{
public string Name
{
get { return name; }
set { name = value; NotifyOfPropertyChange(() => Name); }
}
// Shortening the other properties, but you get the idea...
public IPAddress IP { //etc }
public ComputerStatus Status { //etc }
public DateTime LastUpdated { //etc }
// and so on...
}