C# 为什么ListView的OnDrawItem事件不影响设计时环境?

C# 为什么ListView的OnDrawItem事件不影响设计时环境?,c#,winforms,listview,windows-forms-designer,design-time,C#,Winforms,Listview,Windows Forms Designer,Design Time,如果我创建一个类并使它从一个列表视图中派生,就像这样 class MyListView : ListView { public MyListView() : base() { DoubleBuffered = true; OwnerDraw = true; Cursor = Cursors.Hand; Scrollable = false; } protected override void OnD

如果我创建一个类并使它从一个列表视图中派生,就像这样

class MyListView : ListView
{
    public MyListView() : base()
    {
        DoubleBuffered = true;
        OwnerDraw = true;
        Cursor = Cursors.Hand;
        Scrollable = false;
    }

    protected override void OnDrawItem(DrawListViewItemEventArgs e)
    {
        //base.OnDrawItem(e);
    }
}
然后,我打开windows窗体的设计视图,添加一个新的MyListView对象,然后添加一个项目并将其链接到图像列表。我可以看到mylistview对象中有一项。它对名为
lv
的表单上的对象没有影响,该表单的类型为
MyListView
。另一方面,当我运行我的应用程序时,我完全看到了我所期望的,并且没有列出任何项目

为什么这会影响运行时而不是设计时绘制


答案

ListViewDesigner
shadows
OwnerDraw
控件的属性,如
Visible
Enabled
属性。所以它只在运行时工作,更改它不会影响设计时

旁注

如果查看
ListViewDesigner
的源代码,您将看到以下属性:

private bool OwnerDraw
{
    get { return (bool) base.ShadowProperties["OwnerDraw"]; }
    set { base.ShadowProperties["OwnerDraw"] = value; }
}
[Designer(typeof(ControlDesigner))]
public class MyListView : ListView
PreFilterProperties
中,您将看到设计器将原始属性替换为以下属性:

PropertyDescriptor oldPropertyDescriptor = (PropertyDescriptor) properties["OwnerDraw"];
if (oldPropertyDescriptor != null)
{
    properties["OwnerDraw"] = TypeDescriptor.CreateProperty(typeof(ListViewDesigner), 
        oldPropertyDescriptor, new Attribute[0]);
}
因此,无论您使用什么
视图
,它都会执行默认的绘制,而不管您在
OnDrawItem
中有什么。这是因为它在设计时不使用
OwnerDraw
属性。设计师给它加上阴影。这与您在
启用
可见
属性中看到的行为相同

在运行时启用所有者绘制的变通方法

作为一种解决方法,您可以为派生控件注册不同的
设计器。这样,
OwnerDraw
属性将作为普通属性工作:

private bool OwnerDraw
{
    get { return (bool) base.ShadowProperties["OwnerDraw"]; }
    set { base.ShadowProperties["OwnerDraw"] = value; }
}
[Designer(typeof(ControlDesigner))]
public class MyListView : ListView

警告:请记住,为控件注册新设计器将丢失当前的
ListViewDesigner
功能,如设计器谓词或智能标记(操作列表)窗口或列大小选项。如果您需要这些功能,您可以通过查看
ListViewDesigner
源代码在自定义设计器中实现这些功能。

。。。好吧,我将代码粘贴到一个新的类文件中,然后打开我的表单,单击工具箱并将其拖到表单上。我在表单上选择新对象,并将
LargeImageList
更改为我的imagelist,编辑项目以包括一个带有imagelist中图像的项目,它使用
LargeIcon
的默认
视图。它在设计时显示的项目很好,但运行它时没有显示任何内容。。。你是如何让它工作的,这让我很惊讶。不设置视图属性是一个相当大的错误,在你自定义绘图时非常重要。现在,您只看到它绘制标签,而不是自定义绘制。猜测:不要使用Load事件来更改属性,这很笨拙。我还使用以下代码进行了测试:
this.View=System.Windows.Forms.View.Details;this.OwnerDraw=true;本条第2栏添加(“X”);本条。添加(“1”);本条。添加(“2”)但没什么变化。@汉帕桑我不明白你的逻辑。你的印象是,我在
Load
事件中做了一些事情,而我的印象是我没有。在我的代码中,我只有构造函数的代码,没有任何
Load
事件。
视图
属性已由基类设置。我真的不知道你的评论是朝什么方向发展的。@RezaAghaei你是想把视图设置成细节还是别的什么?因为默认值应该是LargeIcon。是否可以在设计期间以不同的方式显示这些更改?哪些更改?例如,我从
ListViewDesigner
中添加了一些代码,我相信这些代码描述了原因。“有什么变化?”我希望在设计时看到自定义绘制的listview。没有办法看到他们吗?我记得在过去,如果我对PAINT事件做了一些事情,或者它是WM_PAINT消息的子类,以自定义绘制控件。它显示了我在设计时所做的所有更改。例如,我可以改变一种颜色作为道具,它将反映在设计时的形式。我测试了它,它的工作。我会加上它作为一个注释来回答。