【问题标题】:How to remove sorting glyph in datagridview without removing Sorting facility如何在不删除排序工具的情况下删除 datagridview 中的排序字形
【发布时间】:2012-08-08 09:19:16
【问题描述】:

如何从 DataGridView 中的列标题中删除排序字形而不删除其排序功能。

我正在使用 C# 开发 windows 窗体应用程序,我想从 datagridview 生成报告,其中 datagridview 列宽将在报告列中分配,其中 DataGridView 列包含排序字形,这是我的不必要的空间情况下,我想将其从 ColumnHeader 中排除。

【问题讨论】:

    标签: c# winforms datagridview datagridviewcolumn columnsorting


    【解决方案1】:

    使用自定义单元格绘制实际上很容易做到这一点。

    你需要做的就是处理DataGridViewCellPainting事件:

    dataGridView1.CellPainting += new DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting);
    

    在处理程序中做这样的事情:

    void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        if (e.RowIndex == -1)
        {
            e.Paint(e.CellBounds, DataGridViewPaintParts.All &~DataGridViewPaintParts.ContentBackground);
    
            e.Handled = true;
        }
    }
    

    上面的代码非常简单 - 只需检查当前单元格是否在标题行中(具有 -1 索引)然后绘制除 ContentBackground 之外的所有内容。

    我只在我的 Windows 7 机器上检查过它,它看起来不错,内容背景似乎仅用于排序字形 - 您需要在目标环境中对其进行测试以确保您没有需要做更多涉及的自定义绘画以保持 ContentBackground 没有字形。


    标题单元格的宽度仍将包括字形空间。我通常会接受,因为改变它会变得有点混乱,但如果你必须让宽度适合文本,那么类似下面的东西会起作用。

    首先在DataGridView的DataBindingComplete事件中设置宽度:

    void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {        
        if (dataGridView1.AutoSizeColumnsMode == DataGridViewAutoSizeColumnsMode.AllCells)
        {
            // Loop over all the columns
            foreach (DataGridViewColumn c in dataGridView1.Columns)
            {
                // Work out the size of the header text
                Size s = TextRenderer.MeasureText(c.HeaderText, dataGridView1.Font);
    
                // Change the autosize mode to allow us to see if the header cell has the 
                // longest text
                c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
                if (s.Width + 10 > c.Width)
                {
                    // If the header cell is longest we set the column width
                    c.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
                    c.Width = s.Width + 10;
                }
                else
                {
                    // If the header cell is not longest, reset the autosize mode
                    c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                }
            }
        }
    }
    

    完成此操作后,当单元格文本比标题长时,您仍需要允许列自动调整大小。

    为此,我使用了CellValueChanged 事件:

    void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        DataGridViewColumn c = dataGridView1.Columns[e.ColumnIndex];
    
        if (c.AutoSizeMode == DataGridViewAutoSizeColumnMode.None)
        {
            Size s = TextRenderer.MeasureText(dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString(), dataGridView1.Font);
            if (s.Width > c.Width)
            {
                c.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
            }
        }
    
    }
    

    【讨论】:

    • 我想删除字形大小。其中包括 wgeb AutoSizeColumn 在模式为 AllCells 时计算列的大小
    • @HaiderAliWajihi 这变得相当棘手 - 我会考虑更多,但想不出一个好方法。宽度需要是标题单元格或足够长以容纳单元格中最长的内容,这意味着仅根据标题文本设置宽度是行不通的。
    • @HaiderAliWajihi 我找到了一种方法来做到这一点。可能有更清洁的方法,但我想不出。如果是我,我只会使用自定义绘画并接受包括字形的宽度。但您可能会发现此代码适合您。
    • 非常感谢,我认为这可能有效,我会试试这个代码。
    【解决方案2】:

    你不能在 WinForms 中做到这一点,除非你编写一个自定义数据网格视图来满足你的需要,我会说这对你的要求来说有点过头了。

    更新

    我已经为按钮、画布控件创建了自定义进度条,但没有创建自定义数据网格视图。也就是说,这是我这样做的想法......

    实际上,您创建了一个新的UserControl,并向其中添加了一个普通的 DataGridView,并删除了标题。现在在 DataGridControl 上方添加面板,该面板在列标题处“起作用”。您必须处理所有事件,例如单击标题进行排序、调整它们的大小以调整列的大小并调用 DataGridView 上的方法来执行相同的操作。

    如果您想要在用户向下滚动时隐藏列标题的效果,您也必须手动完成。

    抱歉,我无法为您提供比这更可靠的起点。如果您不熟悉创建自定义控件,请尝试创建一个自定义按钮(例如:左侧有一个图像)或进度条,它还会在中间显示进度百分比。你会感觉到你能做什么。

    如果您使用的是 WPF,我认为这样的事情可以轻松完成。

    【讨论】:

    • 如果我制作自定义 datagridview,那我该怎么做呢?
    • thnx 回复,但这可能是一项巨大的工作,我正在开发一个正在开发中的应用程序,我无法尝试这种类型的所有已运行模块的实现。thnx 回复再次
    • 是的,在 WinForms 中创建自定义控件是一项艰巨的任务,需要进行大量测试。在这种情况下,您可能必须对当前结果“满意”。
    【解决方案3】:

    我在尝试使右对齐的标题文本与单元格内容对齐时遇到了同样的问题(在标题文本也没有完全右对齐的一行数字中看起来很傻。)我在其他 dgv 中注意到它可以挤出字形。

    无论如何,真正简单的解决方案,用前导空格填写标题文本,并将标题单元格换行模式设置为 false。示例:

        dgv.Columns["Width"].HeaderText = "        Width";
        dgv["Width"].HeaderCell.Style.WrapMode = DataGridViewTriState.False;
    

    可能需要花一点时间来正确地确定前导空格的数量,但结果是令人满意的。 (不知道它是否适用于尾随空格,太晚了无法尝试。)

    【讨论】:

    • 然而,从这个解决方案中,问题可以被消除,但不是一个好技巧。我有一个可以以任何方式使用的客户 datagridview,我们不能设置 WrapMode = false。
    猜你喜欢
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 2018-02-22
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-28
    相关资源
    最近更新 更多