gpt4 book ai didi

c# - 按属性名称排序列表

转载 作者:行者123 更新时间:2023-12-02 09:02:50 25 4
gpt4 key购买 nike

我编写了一个函数,用于在单击列标题时对 ListView 进行排序。我现在希望该函数适用于任何列。我的第一个想法是传递一个表示列中显示的属性的字符串,并使用 ifswitch 按正确的属性进行排序,例如:

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>

类(class)等:

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...
}

最佳答案

你不需要开关。如果您想按名称访问属性,可以创建一个 Expression 来构建 Func

private bool sortOrder = false;
public void SortCol(string propName)
{
OUModel ou = ADRoot.Descendants().Where(node => node.IsSelected == true).FirstOrDefault() as OUModel;

if (ou != null)
{
if (sortOrder)
ou.Computers = ou.Computers.OrderBy(GetProperty(propName)).ToList();
else
ou.Computers = ou.Computers.OrderByDescending(GetProperty(propName)).ToList();
sortOrder = !sortOrder;
}
}

// this method creates an Expression<Func<RemoteComputer,object>>
// and returning its compiled() resutl. Func<RemoteComputer,object>
// so you can use this `Func` in your orderBy methods.
public Func<T, object> GetProperty<T>(string propertyName)
{
// q =>
ParameterExpression param = Expression.Parameter(typeof(T), "q");
// q.propertyName
// for example : q.Name
MemberExpression member = Expression.PropertyOrField(param, propertyName);
// change property type to object (because we want to use all posible types of our class peroperties or fields)
var body = Expression.Convert(member, typeof(object));
// create Expression<Func<RemoteComputer,object>>
var property = Expression.Lambda<Func<T, object>>(body, param);
// returns a Func<T,object>
return property.Compile();
}

<小时/> 更新

此外,您还可以使用此扩展类向整个应用程序中的列表添加 OrderBy 字符串支持。这也适用于 IQueryable 查询。

public static class OrderByExtentions
{
public static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> list, string propertyName )
{
return list.OrderByDescending(GetPropertyFunc<T>(propertyName));
}
public static IQueryable<T> OrderByDescending<T>(this IQueryable<T> list, string propertyName)
{
return list.OrderByDescending(GetPropertyExpression<T>(propertyName));
}
public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string propertyName)
{
return list.OrderBy(GetPropertyFunc<T>(propertyName));
}
public static IQueryable<T> OrderBy<T>(this IQueryable<T> list, string propertyName)
{
return list.OrderBy(GetPropertyExpression<T>(propertyName));
}
private static Expression<Func<T, object>> GetPropertyExpression<T>(string propertyName)
{
ParameterExpression param = Expression.Parameter(typeof(T), "q");
MemberExpression member = Expression.PropertyOrField(param, propertyName);
var body = Expression.Convert(member, typeof(object));
return Expression.Lambda<Func<T, object>>(body, param);
}
private static Func<T, object> GetPropertyFunc<T>(string propertyName)
{
return GetPropertyExpression<T>(propertyName).Compile();
}
}

用法:

// eg. propName = "Name";

ou.Computers = ou.Computers.OrderByDescending(propName).ToList();

// or

ou.Computers = ou.Computers.OrderBy(propName).ToList();

关于c# - 按属性名称排序列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60132085/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com