ListView - 如何对齐纵向网格线与标题分隔线 - 让最后一列填充空间

5

我正在尝试用C#编写一个Windows Forms音乐播放器应用程序。

该应用程序应该显示一个列表,并有一些播放/停止按钮。

我刚刚开始半个小时,但我的设计几乎完成了。现在我有三件事要修复,一个错误和两个好看的东西:

  1. 在图片上,您可以看到我发现的错误。您可能会说这没什么,但它是一个眼中钉。我如何修复这个问题?

    -

  2. 如何使列标题居中对齐,而不是内容?

  3. 如何使最后一列填充listView的其余部分?


你正在使用列表视图或DataGridView吗? - Mohammad Chamanpara
启用详细信息的listView - user4146732
2个回答

4
  • 您可以设置除第一列标题之外的所有文本的文本对齐方式;它始终是左对齐的。要更改它,您需要自己绘制。

  • 没有自动填充选项,因此您需要编写一个setColumnwidth函数,它循环遍历除最后一列之外的所有列并总结它们的Widths;然后从ListView的Clientsize.Width中减去总和,并设置最后一列的宽度。

  • 我不知道网格线中的显示错误是新问题;到目前为止,我不知道如何修复它;也许自己绘制会有所帮助..?

更新:

以下是一些代码:

void setLastColumnTofill(ListView lv)
{
     int sum = 0;
     int count  = lv.Columns.Count;
     for (int i = 0; i < count   - 1; i++) sum += lv.Columns[i].Width;
     lv.Columns[count   - 1].Width = lv.ClientSize.Width - sum;
}

设置 OwnerDraw = true 后您需要编写三个(全部都需要!)绘制事件:

private void listView1_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
    e.Graphics.FillRectangle(SystemBrushes.Menu, e.Bounds);
    e.Graphics.DrawRectangle(SystemPens.GradientInactiveCaption, 
        new Rectangle(e.Bounds.X , 0, e.Bounds.Width , e.Bounds.Height) );

    string text = listView1.Columns[e.ColumnIndex].Text;
    TextFormatFlags cFlag = TextFormatFlags.HorizontalCenter 
                          | TextFormatFlags.VerticalCenter;
    TextRenderer.DrawText(e.Graphics, text, listView1.Font, e.Bounds, Color.Black, cFlag);
}

private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
    e.DrawDefault = true;
}

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    e.DrawDefault = true;
}

你可能想要稍微调整一下颜色或宽度..
如果你有一个包含用于显示排序顺序(或其他内容)的图像的ImageList,你可以添加它来绘制它们:
 ColumnHeader colH = listView1.Columns[e.ColumnIndex];
 int ii = colH.ImageIndex;
 if (ii >= 0 && ii < imageList1.Images.Count) 
            e.Graphics.DrawImage(imageList1.Images[ii], 
              e.Bounds.Width + e.Bounds.X - imageList1.ImageSize.Width, 0);

enter image description here


它正在工作 :) (我太懒了,不想自己绘制所有这些东西,但自动填充功能最重要)谢谢! - user4146732
我已经添加了填充和自绘的代码 :-) - TaW
完整的答案。我建议使用VisualStyleRenderer来获得更好的外观和感觉。如果您能善意地查看我的帖子并发现它有用,我会很高兴 :) - Reza Aghaei
是的,你说得对,在这种情况下它确实做得很好!+1!请注意,在列宽度例程中应使用LV的ClientSize.Width。我将其放在一个函数中,以便稍后调用它,当事情可能发生变化时。 - TaW
@TaW 我知道这是一个很久以前的解决方案。我遇到了同样的问题,正在寻找确切的解决方案。它有效!除了我的文本在运行时重复出现。一个是原始的,位于顶部垂直对齐,正确的一个位于中心垂直对齐。我正在查看您的“绘制事件”代码,并没有更改任何内容,完全复制了它,但为什么我会得到重复的标题文本?我希望至少你能给我一个提示...谢谢。 - RickyBelmont
嗯,很难说。listView1_DrawColumnHeader事件以FillRectangle开始,应该清除/覆盖原始文本,即使它发生了。你没有在那里放置额外的e.DrawDefault = true,对吧? - TaW

4

OwnerDraw设置为true后,您可以执行其他操作,例如:

绘制ListView

int sortIndex = 0;
private void listView1_DrawColumnHeader(object sender,
   DrawListViewColumnHeaderEventArgs e)
{
    var state = e.State == ListViewItemStates.Selected ?
        VisualStyleElement.Header.Item.Hot : VisualStyleElement.Header.Item.Normal;
    var sortOrder = listView1.Sorting == SortOrder.Ascending ?
        VisualStyleElement.Header.SortArrow.SortedUp :
        VisualStyleElement.Header.SortArrow.SortedDown;
    var itemRenderer = new VisualStyleRenderer(state);
    var sortRenderer = new VisualStyleRenderer(sortOrder);
    var r = e.Bounds; 
    r.X += 1;
    itemRenderer.DrawBackground(e.Graphics, r);
    r.Inflate(-2, 0);
    var flags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter |
        TextFormatFlags.SingleLine;
    itemRenderer.DrawText(e.Graphics, r, e.Header.Text, false, flags);
    var d = SystemInformation.VerticalScrollBarWidth;
    if (e.ColumnIndex == sortIndex) //Sorted Column
        sortRenderer.DrawBackground(e.Graphics, 
            new Rectangle(r.Right - d, r.Top, d, r.Height));
}

private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
    e.DrawDefault = true;  /*Use default rendering*/
}

private void listView1_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
    e.DrawDefault = true;  /*Use default rendering*/
}

使用最后一列填充ListView
private void ListViewSample_Load(object sender, EventArgs e)
{
    var otherItemWisth= this.listView1.Columns.Cast<ColumnHeader>()
        .Where(x => x.Index < this.listView1.Columns.Count - 1)
        .Sum(x => x.Width);
    this.listView1.Columns[this.listView1.Columns.Count - 1].Width = 
        this.listView1.ClientSize.Width - otherItemWisth;
}

结果

在此输入图片描述


(翻译说明:此文为HTML代码,仅翻译内容部分,不包括标签)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接