使用 Windows 窗体数据控件和 DataTable 完成画廊类型的显示? [英] Accomplish gallery-type display with a Windows Forms data control and DataTable?

查看:22
本文介绍了使用 Windows 窗体数据控件和 DataTable 完成画廊类型的显示?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 datatable,如下所示:

I have a datatable that looks like the following:

Room   Cook   Waiter  BG_Image
----------------------------------
201    Joe    Jim     Green.png
202    Jack   Mary    Red.png
203    Jet    Mark    Yellow.png
204    Bob    Bing    Green.png
205    Jack   Mary    Red.png
206    Jane   Burt    Red.png
207    Tina   Mark    Green.png
208    Bob    Jill    Green.png

我需要将此数据绑定到某种类型的数据控件,以便最终结果如下所示:

I need to bind this data to some type of data control, so that the end-result looks like this:

昨天和今天我一直在尝试使用 dataGridView 寻找解决方案,但还没有成功.

Yesterday and today I've been trying to find a solution using the dataGridView, but no luck yet.

具有讽刺意味的是,我在 asp.net 网络表单中做了同样的事情,使用 DataList 更容易.但是对于 WinForm,这是一项更加困难的任务.

Ironically, I did the same exact thing in an asp.net webform, and it was much easier with a DataList. But with a WinForm, it's been a much more difficult task.

所以我的问题是:我可以在 Windows 窗体中使用什么数据控件来绑定到包含的 datatable 以便最终结果类似于我发布的图像?

So my question: what data control can I use in a Windows Form to bind to the included datatable so that the end-result is something similar to the image I posted?

我不是在寻求问题的解决方案,我只是在寻找朝着正确方向前进的动力.

I'm not asking for a solution to the problem, I'm just looking for a push in the right direction.

(如果问题不是很好,请告诉我,我会尝试更改它.如果太模糊,那是因为我没有什么具体的补充.)

(If the question is not well-formed, please let me know and I'll try to change it. And if it's too vague, it's because I have nothing concrete to add.)

推荐答案

克隆你的设计并不难;并使用某种 DataBinding 到您的 DataTable 来显示数据可以通过一些解决方法来实现.

Cloning your design is not hard; and using some sort of DataBinding to your DataTable to display the data can be achieved with a little workaround.

事情会变得更棘手,请阅读:需要更多的努力,当您想要更多而不仅仅是显示数据时.我不会在这里讨论.

Things will get trickier, read: need more effort, when you want more than simply displaying the data. I will not go into that here.

这是一个小例子:

下面的代码只允许您显示数据.没有提供您可以从 DataBinding 获得的任何高级功能,例如导航、编辑、验证..

The code below only lets your display the data. There is no provision for any of the advanced functionality you can get from DataBinding like navigation, editing, validation..

手头的问题实际上由三个独立的问题组成:

The issue at hand really consists of three separate problems:

  • 您想使用 DataBinding多条记录.
  • 您想要一个免费或表格布局,不是面向行的布局.
  • 记录的字段应该进入一个自由布局的显示对象.
  • You want to use DataBinding to multiple records.
  • You want a free or tabular layout, not a row-orientated one.
  • The fields of a record should go into a freely laid out display object.

对于后者,有许多选项可以从所有者绘制的Panel 子类到定制的UserControl.我们选择后者,因为它易于编码且易于扩展.

For the latter there are many options going from a owner-drawn Panel subclass to a custom-made UserControl. Let's go for the latter as it is simple to code and easier to expand.

第二,我们可以在多个容器控件之间进行选择.我会选择 FlowLayoutPanel.

For the second we can choose between several container controls. I'll go for a FlowLayoutPanel.

但是我们如何使用DataBinding?即使我们绑定了 UC 的成员,我们仍然没有获得多记录数据绑定.

But how can we use DataBinding? Even if we bind members of the UC we still don't get multi-record data-binding.

解决方法使用我能想到的一个 Winforms 控件,它提供了多记录数据绑定:一个 DatGridView.但是因为它只会显示一个包含行和列的单元格网格,每个单元格包含一个值,所以我们根本不会让它显示任何内容:

The workaround uses the one Winforms control I can think of that provides multi-record data-binding: A DatGridView. But as it will only display a grid of cells with rows and columns, each cell holding one value, we won't let it display anything at all:

DataGridView dataGridView1 = new DataGridView();
DataTable DT = null;

public Form1()
{
    InitializeComponent();
    dataGridView1.DataSourceChanged += dataGridView1_DataSourceChanged;
}

如您所见,DGV 是严格使用默认值创建的,但并未添加到 Form,因此它不会显示.

As you can see the DGV is created strictly with the default values but not added to the Form, so it doesn't show.

我们只使用它的DataSource(在加载DataTable之后,很明显):

We only use its DataSource (after loading the DataTable, obvioulsy):

private void button1_Click(object sender, EventArgs e)
{
    dataGridView1.DataSource = DT;
}

DataSource 更改时,我们清除用于托管显示控件的 FlowLayoutPanel,并为每个 DataRow 添加一个:

When the DataSource changes we clear the FlowLayoutPanel we use to host the display controls and add one for each DataRow:

private void dataGridView1_DataSourceChanged(object sender, EventArgs e)
{
    DataTable dt = (DataTable)dataGridView1.DataSource;
    flowLayoutPanel1.Controls.Clear();
    foreach (DataRow row in dt.Rows)
    {
        UCBind ucb = new UCBind(row, imageList1);
        flowLayoutPanel1.Controls.Add(ucb);
    }
}

FlowLayoutPanel 让生活变得非常简单;只要确保它的大小可以容纳正确数量的显示控件!但是您也可以将它们添加到 TableLayoutPanel 或什至一个简单的 Panel.对于这些,您需要而且可以确定所有布局细节.

The FlowLayoutPanel makes life very easy; just make sure its size can hold the right number of display controls! But you could also add them to a TableLayoutPanel or even a simple Panel. For these you need to but also can determine all the layout details yourself.

现在是显示控件.

我创建了一个 UserControl UCBind 并在构造函数中传入了一个 DataRow 和一个 ImageList.代码如下所示:

I have created a UserControl UCBind and pass in a DataRow and an ImageList in the constructor. The code looks like this:

public partial class UCBind : UserControl
{
    ImageList imgList { get; set; }

    public UCBind()
    {
        InitializeComponent();
        DoubleBuffered = true;  // prevent flicker
    }

    public UCBind(DataRow row, ImageList imglist)
    {
        InitializeComponent();
        DoubleBuffered = true;  // prevent flicker
        if (row != null)
        {
            imgList = imglist;
            DisplayData(row);
        }
    }

    public void DisplayData(DataRow row)
    {
        lbl_field1.Text = row.Field<int>(0) + "";
        lbl_field2.Text = row.Field<string>(1);
        lbl_field3.Text = row.Field<string>(2);
        if (imgList != null) BackgroundImage = imgList.Images[row.Field<string>(3)];

    }
}

很明显,设计器代码中还有更多内容来设置 UC 及其字段的样式:

Obviously there is a little more going on in the designer code to style the UC and its fields:

  • 添加三个标签
  • DockTop.
  • 设置 AutoSize = false.
  • 放大高度
  • 将他们的 ForeColor 设置为 White.
  • 根据需要更改字体.
  • TextAlignment 设置为 Left、Right &没错.
  • 将所有 BackColors 设置为 Transparent.
  • BackgroundImageLayout 设置为 Stretch.
  • Add three Labels
  • Dock each to the Top.
  • Set AutoSize = false.
  • Enlarge the Height
  • set their ForeColor to White.
  • Change the Fonts as needed.
  • Set TextAlignment to Left, Right & Right.
  • Set all BackColors to Transparent.
  • Set BackgroundImageLayout to Stretch.

您还需要将 Size 设置为您想要的值.

You will also want to set the Size to what you want.

我没有包含设计师生成的代码,因为它往往很长.只需自己创建新的 UserControl 类,添加 Labels、样式和上面几行构造函数代码..!

I have not included the designer genrated code as it tends to be rather long. Simply create the new UserControl class yourself, add the Labels, styling and the few lines of constructor code above..!

为了使它更丰富,您可以尝试添加调整大小的代码,使 FLP 始终填充正确数量的控件.

And to make it rich you could try to add resizing code to make the FLP always fill with the right number of controls.

显然,如果不扭曲图像,圆角和 3d 边框看起来最好.我使用一个 ImageList 和合适的 ColorDepthImageSize 值并加载三个 Images.然后我将一个对它的引用传递给我创建的每个 UC.ImageList 被添加到表单中,你可以在 VS 设计器中将图像加载到其中.:

Obviously the rounded corners and 3d borders will look best if you don't distort the image. I use an ImageList with suitable values for ColorDepth and ImageSize and load the three Images. Then I pass a reference to it to each UC I create.. The ImageList is added to the form and you can load the images into it right in the VS designer..:

这篇关于使用 Windows 窗体数据控件和 DataTable 完成画廊类型的显示?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆