asp.net 基于column1对列值进行排序,并将其放在GridView中的列2中

gc0ot86w  于 2022-12-15  发布在  .NET
关注(0)|答案(1)|浏览(144)

我有一个名为column 1的列,希望排在column 2中:

Column1  Column2

500       3
1000      4
20        1
310       2

我所尝试的是从Column 1中获取列值并将其放入数组中:

for (int us = 0; us < GridView1.Rows.Count; us++)
                {
double[] doubleArray = new double[] { Convert.ToDouble(GridView1.Rows[us].Cells[1].Text) };

}
然后分类:

Array.Sort(doubleArray);

然后将其放入第2列:

GridView1.Rows[us].Cells[2].Text += doubleArray[us];

这并不使排名只给出误差;

bjp0bcyl

bjp0bcyl1#

这是一个可爱的问题!
你看,如果我们用一个列的值来填充一个数组,我们想要“排名”,那么我们就失去了它属于哪个网格行的信息。
显然,网格可以按姓氏、酒店名称或某个日期排序--我们不在乎,但仍然需要对给定列进行排名(比如成本值、名字--谁在乎呢!!!)。
按理说(超出情理),GV当前排序在这里是不相关的!!!
对特定列值的排序必须100%独立于当前网格排序,并且必须基于我们要排序的特定列100%独立于当前网格排序。
如前所述,如果我们将这样的值拉入数组,然后进行排序,我们首先会“丢失”该值所属的行。
因此,我们需要抓取/获取/拥有/使用/享受网格行和值,然后排序,然后将值放回GV,但要确保值返回到正确的/当前GV行!
所以,我们需要一些东西,将允许我们排序的价值+保持当前的GV行!
这将工作:
首先,我们的GV飞机简标记:

<asp:GridView ID="GridView1" runat="server" ClientIDMode="Static"
    AutoGenerateColumns="False" DataKeyNames="ID"
    CssClass="table table-hover" Width="40%" ShowHeaderWhenEmpty="true">
    <Columns>
        <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
        <asp:BoundField DataField="LastName" HeaderText="LastName" />
        <asp:BoundField DataField="HotelName" HeaderText="HotelName"  HeaderStyle-Width="120"/>
        <asp:BoundField DataField="City" HeaderText="City" />
        <asp:BoundField DataField="Description" HeaderText="Description" />
        <asp:BoundField DataField="Price" HeaderText="Night Rate"  DataFormatString="{0:n2}"/>
        <asp:TemplateField HeaderText =" Rank (Price)" >
            <ItemTemplate>
                <asp:Label ID="lblRank" runat="server" ></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:Button ID="cmdEdit" runat="server" Text="Edit"
                    CssClass="btn myshadow"
                    OnClick="cmdEdit_Click"/>
            </ItemTemplate>
        </asp:TemplateField>

    </Columns>
</asp:GridView>
<asp:Button ID="cmdRank" runat="server" Text="Rank" Width="111px" 
    CssClass="btn" OnClick="cmdRank_Click" />

和要加载的代码:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
        LoadGrid();
}

void LoadGrid()
{
        
    GridView1.DataSource = MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName");
    GridView1.DataBind();
}

DataTable MyRst(string strSQL)
{
    DataTable rstData = new DataTable();
    using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
    {
        using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
        {
            cmdSQL.Connection.Open();
            rstData.Load(cmdSQL.ExecuteReader());
        }
    }
    return rstData;
}

现在我们有了这个

因此,gv是按酒店名称排序的,但我们现在需要根据房价填写“排名”一栏。
这段代码显然可以/将在我们加载gv之后运行,但我有这个答案的代码分开。
因此,下面的代码应该可以完成这个任务:

protected void cmdRank_Click(object sender, EventArgs e)
{
    SortedDictionary<decimal, int> MyRank = new SortedDictionary<decimal,int>();

    foreach (GridViewRow gRow in GridView1.Rows)
        MyRank.Add(Convert.ToDecimal(gRow.Cells[5].Text),gRow.RowIndex);

    // above is our sorted list, now put rank values into GV
    int i = 0;
    foreach (KeyValuePair<decimal, int> OneRank in MyRank)
    {
        GridViewRow gRow = GridView1.Rows[OneRank.Value];
        Label lRank = (Label)gRow.FindControl("lblRank");
        lRank.Text = (i + 1).ToString();
        i++;
    }
}

我们现在看到这个:

因此,排序后的“Dictionary”项在添加时进行排序,并将“key”保存为要排序的值。
现在,公平地说,如果rank值有重复的值,那么我们必须做kluge。
因此,在上面,我们有数字,所以这将解决这个问题:

foreach (GridViewRow gRow in GridView1.Rows)
        {
            decimal Price = Convert.ToDecimal(gRow.Cells[5].Text);
            while (MyRank.ContainsKey(Price))
                Price += 0.0001m;

        MyRank.Add(Price,gRow.RowIndex);
        }

我想如果我们说按名字排名的话?
那么我们有一个字符串--而不是一个数字,在这种情况下,重复的是什么?
嗯,我会在上面的循环末尾加上字母“A”,直到没有匹配。

编辑:我们现在更改了问题、新问题和新标准

这是软件开发的一个很好的教训。当你没有正确定义问题时,你就不能编写解决方案。改变问题也意味着你要重写软件。这是非常昂贵的时间和金钱。
所以,我们从一些样本数据开始--但没有提到重复。而且我们还再次改变了标准。换句话说,我们不仅要排名,而且要给相同值的数字同样的排名。
以上是一个很好的例子,说明了为什么我们在编写代码之前要把手头的问题写在纸上。每一个新事物,每一个新标准,每一个新变化都会对代码的编写产生不同的要求。
请记住,作为开发人员,我们不会活到150岁或200岁。因此,我们必须“限制”和“优化”我们编写的代码。否则,我们整天花在SO上,我们会饿死,并造成许多世界贫困。
所以,正如你所看到的,这个问题现在已经演变成了一套不同的规则,不同的标准,以及一大堆新的概念和问题的补充。当编写代码时,我们限制在所需的知识范围内,因为正如所指出的,我们都活不到200岁。所以,一个关于如何不问问题的很好的例子,这是一个很好的例子,说明当你没有正确定义问题时会发生什么。
现在我们有了新的信息。新的信息是我们想要排序的东西会出现重复,但也有一个新的规则是重复的值会被赋予相同的排序值。
在我最初的解决方案中,我使用行号表示秩!所以,如果我们在第3行,那么秩= 3。这节省了代码,节省了变量,是开发人员自然“优化”代码的典型方式。(同样,我们基于给定的问题这样做,因为如果一个人要对每一个可能的结果进行编码,那么我们不仅会增加解决方案的成本,但也可能耗尽食物和资源来完成代码或项目。
好了,有了这些新的信息,新的问题,新的标准和规范,然后我们必须编写一些代码,更好地处理问题的扩展范围。
这也是为什么最好在我们开始编码之前对问题进行修改(事实证明,对写好的问题进行修改要容易得多,然后才是编码!!!)。因此,我们现在可以掌握和理解为什么我们在开始编码之前定义问题!!!
因此,这段代码工作得更好,并且“假设”重复将会并且可能存在。在最初的问题中,我没有做这样的假设。结果我们不得不添加一个“创可贴”或“kluge”来处理新的问题(重复)。那个创可贴是递增循环(但是,我们可能真的想在这里去掉那个概念)。
所以,最初的代码并不那么理想,但它是基于所提供的问题和信息。
因此,我建议使用这段代码。同样,上面的标记也很好。但是,由于这个问题意味着“行”的秩与行号是分离的,那么我们现在需要一个秩的计数器。

因此,该代码对当前问题和难题具有较强的可操作性。
首先,我们删除了dictionay,因为它运行良好,但不处理重复项。
因此,我们仍然需要获取/抓取/保存“key value”,然后是行号(这样我们以后就可以把rank值推到那一行中)。

var Ranks = new List<KeyValuePair<decimal,int>>();      
foreach (GridViewRow gRow in GridView1.Rows)
{
    decimal Price = Convert.ToDecimal(gRow.Cells[5].Text);
    Ranks.Add(new KeyValuePair<decimal,int>(Price, gRow.RowIndex)); 
}            
Ranks = Ranks.OrderBy(o => o.Key).ToList(); 
int Rank = 0;
decimal LastValue = -1;
foreach (KeyValuePair<decimal,int> OneRank in Ranks)
{
    if (LastValue != OneRank.Key)
        Rank++;
    LastValue = OneRank.Key;
    GridViewRow gRow = GridView1.Rows[OneRank.Value];
    Label lRank = (Label)gRow.FindControl("lblRank");
    lRank.Text = Rank.ToString();
}

相关问题