【问题标题】:How to create user control for displaying collection of other user controls in WinForms?如何创建用户控件以在 WinForms 中显示其他用户控件的集合?
【发布时间】:2015-04-28 14:25:52
【问题描述】:

我需要创建一个用户控件MyTypeListControl 来显示MyType 类型的对象集合,并为每个对象使用用户控件MyTypeDisplayControl 实例。

这样我就可以

  1. MyTypeListControl 的实例添加到我的WinForm,然后
  2. 加载MyType
  3. 的集合
  4. 将其分配给MyTypeListControl 的数据源。

在结果中,它应该在MyTypeListControl 的实例中生成并显示适当的MyTypeDisplayControl 实例计数。

如果我需要显示属性列表 - 等价的将是 DataGrid,将 MyType 中的特定字段分配给特定 DataGrid 的列,但我想以用户身份查看每个 MyType 项目控制 - 比 DataGrid 提供的行更强大的视觉表示和功能。

这可能吗?

I found this SO resource如何创建我的集合类型,但这只是问题解决的一小部分...

【问题讨论】:

  • 为什么不使用 FlowLayoutPanel?除非我误解了您的问题,否则您可以通过将它们添加到 FlowLayoutPanel 来显示您的用户控件列表,并且您也可以轻松地操作集合。
  • @JoshL。我可以将控件集合添加到 FlowLayoutPanel,类似于 DataGrid.DataSource = ICollection?您的意思是使用 Controls 集合进行操作吗?
  • @downvoters - 这个问题有什么问题?如果您能说明问题所在,这将很有帮助,以便我改进;)
  • @JoshL 谢谢,如果有帮助,我会看看
  • FlowLayoutPanel 没有像 DataGrid.DataSource 这样的东西,这将是您必须自己实现的东西(或者您可以在 UserControl 的模型中实现 INotifyPropertyChanged)。

标签: c# winforms user-controls


【解决方案1】:

这很容易(如果你知道怎么做的话),而且并不像你一开始想的那么费力(至少对于处理少于 100 个项目的集合的简单实现而言)。

首先让我们创建一个 MyType:

public class MyType
{
    public static MyType Empty = new MyType(String.Empty, DateTime.MinValue);

    public MyType(string myName, DateTime myBirthday)
    {
        MyName = myName;
        MyBirthday = myBirthday;
    }

    public DateTime MyBirthday { get; private set; }

    public string MyName { get; private set; }
}

接下来我们需要一个 MyTypeControl:

public partial class MyTypeControl : UserControl
{
    private MyType _MyType;
    private Label labelBirthday;
    private Label labelName;
    private Label labelSeparator;

    public MyTypeControl()
    {
        InitializeComponent();
    }

    public event EventHandler MyTypeChanged;

    public MyType MyType
    {
        get { return _MyType; }
        set
        {
            if (_MyType == value)
                return;

            _MyType = value ?? MyType.Empty;
            OnMyTypeChanged(EventArgs.Empty);
        }
    }

    protected virtual void OnMyTypeChanged(EventArgs eventArgs)
    {
        UpdateVisualization();
        RaiseEvent(MyTypeChanged, eventArgs);
    }

    protected void UpdateVisualization()
    {
        SuspendLayout();

        labelName.Text = _MyType.MyName;
        labelBirthday.Text = _MyType.MyBirthday.ToString("F");
        labelBirthday.Visible = _MyType.MyBirthday != DateTime.MinValue;

        ResumeLayout();
    }

    private void InitializeComponent()
    {
        labelName = new Label();
        labelBirthday = new Label();
        labelSeparator = new Label();
        SuspendLayout();
        labelName.Dock = DockStyle.Top;
        labelName.Location = new Point(0, 0);
        labelName.TextAlign = ContentAlignment.MiddleCenter;
        labelBirthday.Dock = DockStyle.Top;
        labelBirthday.TextAlign = ContentAlignment.MiddleCenter;
        labelSeparator.BorderStyle = BorderStyle.Fixed3D;
        labelSeparator.Dock = DockStyle.Top;
        labelSeparator.Size = new Size(150, 2);
        Controls.Add(labelSeparator);
        Controls.Add(labelBirthday);
        Controls.Add(labelName);
        MinimumSize = new Size(0, 48);
        Name = "MyTypeControl";
        Size = new Size(150, 48);
        ResumeLayout(false);
    }

    private void RaiseEvent(EventHandler eventHandler, EventArgs eventArgs)
    {
        var temp = eventHandler;

        if (temp != null)
            temp(this, eventArgs);
    }
}

然后是我们神奇的列表控件:

public class MyTypeListControl : UserControl
{
    private ObservableCollection<MyType> _Items;

    public MyTypeListControl()
    {
        AutoScroll = true;
        _Items = new ObservableCollection<MyType>();
        _Items.CollectionChanged += OnItemsCollectionChanged;
    }

    public Collection<MyType> Items
    {
        get { return _Items; }
    }

    private void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        UpdateVisualization();
    }

    private void UpdateVisualization()
    {
        SuspendLayout();
        Controls.Clear();

        foreach (var item in _Items)
        {
            var control = new MyTypeControl { MyType = item, Dock = DockStyle.Top };
            Controls.Add(control);
            Controls.SetChildIndex(control, 0);
        }

        ResumeLayout();
    }
}

现在只需在表单或父控件中创建列表控件,并用一些有意义的值填充它:

myTypeListControl.Items.Add(new MyType("Adam", DateTime.UtcNow.Add(-TimeSpan.FromDays(365 * 40))));
myTypeListControl.Items.Add(new MyType("Eva", DateTime.UtcNow.Add(-TimeSpan.FromDays(365 * 38))));

【讨论】:

  • 谢谢,这看起来很有希望 - 我会在检查此解决方案时发表评论
  • 是的,这是按预期工作的!我仍然不明白为什么这个问题得到如此负面的评价,但主要是我得到了一个很好的答案!如果您不介意,我将添加一个小更新 - 以便解决方案接受 MyType-s 的集合
猜你喜欢
  • 1970-01-01
  • 2012-03-21
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多