在c#.NET中创建自定义项目可滚动列表视图的最佳方法是什么?

时间:2014-04-21 13:00:50

标签: c# .net listview

我想使用.NET创建GUI应用程序,我需要使用自定义项实现这种可滚动列表。所有项目应分组到3个不同的组,并包括图像,文本和喜欢的星形按钮,如下所示:

mockup

我还想使用搜索框实现过滤,但是一旦我能够创建具有可自定义项目的列表,那么我希望它会更容易。

我尝试使用.NET列表视图,但我希望每个单元格看起来像一个单元格 - 图像,文本,图像之间没有任何边框。

我非常感谢有关这种方式的任何想法!

1 个答案:

答案 0 :(得分:1)

最好的方法是为WPF ListViewListBox控制制作控制模板。

例如,ListBox.ItemTemplate允许查看自定义项目。

如果您想使用第三方组件,Better ListView允许使用所有者绘图(需要子类化BetterListView):

enter image description here

以下是控件的设置代码:

this.customListView = new CustomListView
                        {
                            Dock = DockStyle.Fill,
                            Parent = this
                        };

this.customListView.BeginUpdate();

for (int i = 0; i < 6; i++)
{
    var item = new BetterListViewItem
                {
                    Image = imageGraph,
                    Text = String.Format("Item no. {0}", i)
                };

    this.customListView.Items.Add(item);
}

var group1 = new BetterListViewGroup("First group");
var group2 = new BetterListViewGroup("Second group");
var group3 = new BetterListViewGroup("Third group");

this.customListView.Groups.AddRange(new[] { group1, group2, group3 });

this.customListView.Items[0].Group = group1;
this.customListView.Items[1].Group = group1;

this.customListView.Items[2].Group = group2;
this.customListView.Items[3].Group = group2;
this.customListView.Items[4].Group = group2;

this.customListView.Items[5].Group = group3;

this.customListView.AutoSizeItemsInDetailsView = true;
this.customListView.GroupHeaderBehavior = BetterListViewGroupHeaderBehavior.None;
this.customListView.ShowGroups = true;

this.customListView.LayoutItemsCurrent.ElementOuterPadding = new Size(0, 8);

this.customListView.EndUpdate();

CustomListView类(实现自定义绘图和与星形图标的交互):

using BetterListView;

internal sealed class CustomListView : BetterListView
{
    private const int IndexUndefined = -1;

    private Image imageStarNormal;
    private Image imageStarHighlight;

    private int lastStarIndex = IndexUndefined;
    private int currentStarIndex = IndexUndefined;

    public CustomListView()
    {
        this.imageStarNormal = Image.FromFile("icon-star-normal.png");
        this.imageStarHighlight = Image.FromFile("icon-star-highlight.png");
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);

        var item = HitTest(e.Location).ItemDisplay;

        if (item == null)
        {
            return;
        }

        var bounds = GetItemBounds(item);

        if (bounds == null)
        {
            return;
        }

        Rectangle boundsStar = GetStarBounds(bounds);

        UpdateStarIndex(boundsStar.Contains(e.Location)
            ? item.Index
            : IndexUndefined);
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        base.OnMouseLeave(e);
        UpdateStarIndex(IndexUndefined);
    }

    protected override void OnDrawGroup(BetterListViewDrawGroupEventArgs eventArgs)
    {
        eventArgs.DrawSeparator = false;

        base.OnDrawGroup(eventArgs);
    }

    protected override void OnDrawItem(BetterListViewDrawItemEventArgs eventArgs)
    {
        base.OnDrawItem(eventArgs);

        Graphics g = eventArgs.Graphics;
        BetterListViewItemBounds bounds = eventArgs.ItemBounds;

        int imageWidth = this.imageStarNormal.Width;
        int imageHeight = this.imageStarNormal.Height;

        g.DrawImage(
            (this.currentStarIndex == eventArgs.Item.Index) ? this.imageStarHighlight : this.imageStarNormal,
            GetStarBounds(bounds),
            0, 0, imageWidth, imageHeight,
            GraphicsUnit.Pixel);

        Rectangle boundsSelection = bounds.BoundsSelection;

        g.DrawRectangle(
            Pens.Gray,
            new Rectangle(boundsSelection.Left, boundsSelection.Top, boundsSelection.Width - 1, boundsSelection.Height - 1));
    }

    private void UpdateStarIndex(int starIndex)
    {
        if (starIndex == this.lastStarIndex)
        {
            return;
        }

        bool isUpdated = false;

        if (this.lastStarIndex != IndexUndefined)
        {
            Items[this.lastStarIndex].Invalidate();

            isUpdated = true;
        }

        if (starIndex != IndexUndefined)
        {
            Items[starIndex].Invalidate();

            isUpdated = true;
        }

        this.lastStarIndex = this.currentStarIndex;
        this.currentStarIndex = starIndex;

        if (isUpdated)
        {
            RedrawItems();
        }
    }

    private Rectangle GetStarBounds(BetterListViewItemBounds bounds)
    {
        Rectangle rectInner = bounds.BoundsInner;

        int widthImage = this.imageStarNormal.Width;
        int heightImage = this.imageStarNormal.Height;

        return (new Rectangle(
            rectInner.Width - widthImage,
            rectInner.Top + ((rectInner.Height - heightImage) >> 1),
            widthImage,
            heightImage));
    }
}