Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按属性名称排列的订单列表_C#_Wpf_Data Binding_Caliburn.micro - Fatal编程技术网

C# 按属性名称排列的订单列表

C# 按属性名称排列的订单列表,c#,wpf,data-binding,caliburn.micro,C#,Wpf,Data Binding,Caliburn.micro,我编写了一个函数,用于在单击列标题时对ListView进行排序。我现在希望该函数适用于任何列。我的第一个想法是传递一个表示列中显示的属性的字符串,并使用if或switch按正确的属性排序,例如: private bool sortOrder = false; public void SortCol(string property) { OUModel ou = ADRoot.Descendants().Where(node => node.IsSelected == true).F

我编写了一个函数,用于在单击列标题时对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;
    }
}
private bool sortOrder=false;
公共void SortCol(字符串属性)
{
OUModel ou=ADRoot.subjects()。其中(node=>node.IsSelected==true)。FirstOrDefault()作为OUModel;
如果(ou!=null)
{
交换机(属性)
{
案例“名称”:
如果(排序器)
{
ou.Computers=新列表(ou.Computers.OrderBy(c=>c.Name));
}
其他的
{
ou.Computers=新列表(ou.Computers.OrderByDescending(c=>c.Name));
}
打破
案例“LastUpdated”:
如果(排序器)
{
ou.Computers=新列表(ou.Computers.OrderBy(c=>c.LastUpdated));
}
其他的
{
ou.Computers=新列表(ou.Computers.OrderByDescending(c=>c.LastUpdated));
}
打破
//等等。。。
}
sortOrder=!sortOrder;
}
}
但这显然会变得相当漫长和重复。相反,我想知道我是否可以通过财产本身。但是我试图从XAML(使用Caliburn.Micro操作)传递属性类型,但不知道如何传递

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;
    }
}
private bool sortOrder=false;
公共无效SortCol(Func属性)
{
OUModel ou=ADRoot.subjects()。其中(node=>node.IsSelected==true)。FirstOrDefault()作为OUModel;
如果(ou!=null)
{
如果(排序器)
{
ou.Computers=新列表(ou.Computers.OrderBy(属性));
}
其他的
{
ou.Computers=新列表(ou.Computers.OrderByDescending(属性));
}
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 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...
}

课程等:

    <!-- 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 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...
}
class-ADTreeViewModel:OUModel
{    

public-OUModel-ADRoot{get;set;}=new-OUModel(null,false);//您不需要开关。如果您想通过名称访问属性,您可以创建一个
表达式来构建
函数

private bool sortOrder=false;
公共void SortCol(字符串propName)
{
OUModel ou=ADRoot.subjects()。其中(node=>node.IsSelected==true)。FirstOrDefault()作为OUModel;
如果(ou!=null)
{
如果(排序器)
ou.Computers=ou.Computers.OrderBy(GetProperty(propName)).ToList();
其他的
ou.Computers=ou.Computers.OrderByDescending(GetProperty(propName)).ToList();
sortOrder=!sortOrder;
}
}
//此方法创建一个表达式
//并返回其编译后的()resutl.Func
//因此,您可以在orderBy方法中使用这个'Func'。
公共函数GetProperty(字符串属性名称)
{
//q=>
ParameterExpression param=表达式参数(typeof(T),“q”);
//q.propertyName
//例如:q.Name
MemberExpression member=Expression.PropertyOrField(参数,propertyName);
//将属性类型更改为object(因为我们希望使用类属性或字段的所有可能类型)
var body=Expression.Convert(成员,typeof(对象));
//创建表达式
var property=Expression.Lambda(body,param);
//返回一个Func
返回property.Compile();
}

更新

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

公共静态类OrderByExtensions
{
公共静态IOrderedEnumerable OrderByDescending(此IEnumerable列表,字符串propertyName)
{
return list.OrderByDescending(GetPropertyFunc(propertyName));
}
公共静态IQueryable OrderByDescending(此IQueryable列表,字符串propertyName)
{
return list.OrderByDescending(GetPropertyExpression(propertyName));
}
公共静态IOrderedEnumerable OrderBy(此IEnumerable列表,字符串propertyName)
{
return list.OrderBy(GetPropertyFunc(propertyName));
}
公共静态IQueryable OrderBy(此IQueryable列表,字符串propertyName)
{
return list.OrderBy(GetPropertyExpression(propertyName));
}
私有静态表达式GetPropertyExpression(字符串propertyName)
{
ParameterExpression param=表达式参数(typeof(T),“q”);
MemberExpression member=Expression.PropertyOrField(参数,propertyName);
var body=Expression.Convert(成员,typeof(对象));
返回表达式.Lambda(body,param);
}
私有静态函数GetPropertyFunc(字符串propertyName)
{
返回GetPropertyExpression(propertyName.Compile();
}
}
用法:

// eg. propName = "Name";

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

// or

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

非常好,谢谢。请你解释一下
GetProperty
方法好吗?@Daniel我在每个步骤上都添加了一些注释。希望如此help@Daniel如果您不介意,请将您的问题标题更改为类似于
OrderBy list by property name
,这样您可以帮助其他有类似问题的人。