gpt4 book ai didi

C# 自定义列表框 GUI

转载 作者:太空狗 更新时间:2023-10-30 00:03:32 25 4
gpt4 key购买 nike

我有一个类列表,但是不同的 child 有不同的属性需要显示。

我想要实现的是在 gui 中有一个列表框类型的控件,它使每个子级都能以它想要的方式显示它的属性 - 所以不要为每个类使用相同的预定义列。

我设想了一些类似传输接口(interface)(如下)的东西,每个类都可以在其中绘制自己的条目,显示一些文本、进度条(如果相关)等。

enter image description here

这在 C# 中如何实现?

感谢您的帮助。

最佳答案

让您的列表项实现一个接口(interface),提供显示所需的一切:

public interface IDisplayItem
{
event System.ComponentModel.ProgressChangedEventHandler ProgressChanged;
string Subject { get; }
string Description { get; }
// Provide everything you need for the display here
}

传输对象不应显示自己。您不应混合域逻辑(业务逻辑)和显示逻辑。

自定义列表框:为了以您自己的方式显示列表框项目,您必须从 System.Windows.Forms.ListBox 派生您自己的列表框控件。在构造函数中将列表框的 DrawMode 属性设置为 DrawMode.OwnerDrawFixedDrawMode.OwnerDrawVariable(如果项目大小不同) .如果您使用 OwnerDrawVariable,那么您还必须覆盖 OnMeasureItem,以便告知列表框每个项目的大小。

public class TransmissionListBox : ListBox
{
public TransmissionListBox()
{
this.DrawMode = DrawMode.OwnerDrawFixed;
}

protected override void OnDrawItem(DrawItemEventArgs e)
{
e.DrawBackground();
if (e.Index >= 0 && e.Index < Items.Count) {
var displayItem = Items[e.Index] as IDisplayItem;
TextRenderer.DrawText(e.Graphics, displayItem.Subject, e.Font, ...);
e.Graphics.DrawIcon(...);
// and so on
}
e.DrawFocusRectangle();
}
}

您可以让您的原始传输类实现 IDisplayItem 或为此目的创建一个特殊类。您还可以在列表中包含不同类型的对象,只要它们实现了接口(interface)即可。关键是,显示逻辑本身在控件中,传输类(或任何类)仅提供所需的信息。

示例:由于与 Mark 的持续讨论,我决定在此处包含一个完整示例。让我们定义一个模型类:

public class Address : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
if (_Name != value) {
_Name = value;
OnPropertyChanged("Name");
}
}
}

private string _City;
public string City
{
get { return _City; }
set
{
if (_City != value) {
_City = value;
OnPropertyChanged("City");
OnPropertyChanged("CityZip");
}
}
}

private int? _Zip;
public int? Zip
{
get { return _Zip; }
set
{
if (_Zip != value) {
_Zip = value;
OnPropertyChanged("Zip");
OnPropertyChanged("CityZip");
}
}
}

public string CityZip { get { return Zip.ToString() + " " + City; } }

public override string ToString()
{
return Name + "," + CityZip;
}

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}

#endregion
}

这是一个自定义列表框:

public class AddressListBox : ListBox
{
public AddressListBox()
{
DrawMode = DrawMode.OwnerDrawFixed;
ItemHeight = 18;
}

protected override void OnDrawItem(DrawItemEventArgs e)
{
const TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter;

if (e.Index >= 0) {
e.DrawBackground();
e.Graphics.DrawRectangle(Pens.Red, 2, e.Bounds.Y + 2, 14, 14); // Simulate an icon.

var textRect = e.Bounds;
textRect.X += 20;
textRect.Width -= 20;
string itemText = DesignMode ? "AddressListBox" : Items[e.Index].ToString();
TextRenderer.DrawText(e.Graphics, itemText, e.Font, textRect, e.ForeColor, flags);
e.DrawFocusRectangle();
}
}
}

在表单上,​​我们放置了这个 AddressListBox 和一个按钮。在表单中,我们放置了一些初始化代码和一些按钮代码,这些代码会更改我们的地址。我们这样做是为了查看我们的列表框是否自动更新:

public partial class frmAddress : Form
{
BindingList<Address> _addressBindingList;

public frmAddress()
{
InitializeComponent();

_addressBindingList = new BindingList<Address>();
_addressBindingList.Add(new Address { Name = "Müller" });
_addressBindingList.Add(new Address { Name = "Aebi" });
lstAddress.DataSource = _addressBindingList;
}

private void btnChangeCity_Click(object sender, EventArgs e)
{
_addressBindingList[0].City = "Zürich";
_addressBindingList[1].City = "Burgdorf";
}
}

单击按钮时,AddressListBox 中的项目会自动更新。请注意,仅定义了列表框的数据源。 DataMember 和 ValueMember 保持为空。

关于C# 自定义列表框 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8156141/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com