【问题标题】:WPF : Dynamically create a grid with specified x rows and y columns with static image in each cellWPF:在每个单元格中动态创建具有指定 x 行和 y 列的网格,并带有静态图像
【发布时间】:2013-11-21 08:23:13
【问题描述】:

问题: 我是 WPF 的新手,我无法弄清楚这一点。 如何创建具有 x 行和 y 列的网格并在运行时将图像插入每个单元格?

场景: 我有一个库存项目,最终用户将在其中搜索一个项目,应用程序将指定他可以在哪里找到该项目。现在,我已经在检索保存物品的柜子细节,这些细节又具有 x 行和 y 列的机架。显示的机架可以有不同的行或列大小。参见图片。

方法: 所以我发现我应该有一个 x 行和 y 列的网格(仅在运行时知道)。为每个单元格值填充图像。将不同的图像插入项目的位置或突出显示该单元格值。但我无法找到如何做到这一点。我的大部分搜索都指向动态添加行和列。我是否遗漏了一些非常明显的东西?

预期输出: 下面给出了我希望它如何显示给我的最终用户:

【问题讨论】:

  • 表格的大小是固定的吗?
  • 没有。不同的机架有不同的行数和列数。因此,一旦用户搜索,我们就会确定它是哪个机柜和机架。然后创建一个表格(网格),其中包含我们找到的机架的行 X 列。在此之后,它将只是一个静态显示。
  • 你可以看看here。它允许您绑定行/列计数并具有代码示例。
  • @DamenEU:让我试试。看起来像我可能需要的。

标签: c# wpf xaml


【解决方案1】:

就像我说的,我一直想知道在我们有静态数据的情况下是否需要使用数据网格。所以这就是我想出的。我创建了一个堆栈面板并添加了 y 个图像。现在我添加 x 个这样的堆栈面板。 如果图像的确切位置出现,我会添加一个突出显示的图像。完美地工作。为任何想要重用代码的人共享代码。

private void CreateGraphicalDisplay(int rows,int columns,int row,int column)
    {
        ClearGraphicPanel();
        for (int i = 1; i <= rows; i++)
        {

        StackPanel childstack = new StackPanel();


            for (int j = 1; j <= columns; j++)
            {
                Image gage = new Image();
                gage.Stretch = Stretch.Fill;

                if (i == row && j == column)
                {
                    gage.Source = new BitmapImage(new Uri(@Highlightedimage));
                }
                else
                {
                    gage.Source = new BitmapImage(new Uri(@NormalImage));
                }
                gage.Width = 12;
                gage.Height =12;
                gage.HorizontalAlignment = HorizontalAlignment.Left;
                gage.Margin = new Thickness(10, 1, 1, 1);

                childstack.Children.Add(gage);
            }

            containerstack.Children.Add(childstack);
        }

    }

【讨论】:

  • 我认为这与通常建议的方法不同。所以请大家发表你的看法。这正是我所要求的网格结构。
【解决方案2】:

你可以试试这样的

Xmal

  <Grid>
    <ItemsControl ItemsSource="{Binding A}" >
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal" >
                    <Label Content="{Binding Heading}" BorderThickness="2, 0, 2, 2" BorderBrush="Black"/>
                    <ItemsControl ItemsSource="{Binding Values}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <Label Content="{Binding}" BorderThickness="0, 0, 2, 2" BorderBrush="Black"/>

                                </StackPanel>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

查看模型

class ViewModel
{
    public List<Inventory> A
    {
        get;
        set;
    }

    public ViewModel()
    {
        A = new List<Inventory>();

        for (int i = 1; i <10; i++)
        {
            Inventory iv = new Inventory();
            iv.Heading = "R" + i ;
            iv.Values = new List<string>();
            for (int j = 0; j < 5; j++)
            {
                iv.Values.Add("Pic");
            }
            A.Add(iv);
        }
    }
}

public class Inventory
{
    public string Heading
    {
        get;
        set;
    }

    public List<string> Values
    {
        get;
        set;
    }
}

【讨论】:

    【解决方案3】:

    您可以使用标准的DataGrid 来执行此操作。您可以在 MSDN 上的 DataGrid Class 页面上了解如何使用其中之一。通常在使用这些控件时,您将Bind 自定义数据类型类实例的集合添加到DataGrid.ItemsSource 属性,DataGrid 将为集合中的每个项目添加一行,并为数据中的每个属性添加一列类型类。

    由于您希望拥有可变数量的列,这会给您带来问题。但是,您可以使用 .NET 中的 Anonymous Types。这基本上使您能够在运行时定义一个匿名类,以便您可以根据需要定义尽可能多的属性列。您可以在 MSDN 上的Anonymous Types (C# Programming Guide) 页面了解如何使用它们。

    我给您的最后一个提示是,您希望在匿名类中拥有string 属性,这些属性提供相关的图像路径,用于在每列中显示您想要的任何图像。然后,您可以声明一个DataTemplate 来定义每个单元格的外观(一个Image)...为此,您的string 文件路径需要采用以下格式-/YourAppName;component/YourImageFolderName/YourImageName.jpg

    <DataGrid ItemsSource="{Binding YourAnonymousTypedCollection}">
        <DataGrid.ItemTemplate>
            <DataTemplate>
                <Image Source="{Binding}" />
            </DataTemplate>
        </DataGrid.ItemTemplate>
    </DataGrid>
    

    您可以从 MSDN 上的 ItemsControl.ItemTemplate PropertyData Templating Overview 页面了解更多信息。

    以防万一有人不清楚,我还添加了指向 MSDN 上 Anonymous Types (C# Programming Guide) 页面的链接,以便任何不了解的人都可以了解整个故事。因此,您的第一条评论是不必要的,对任何人都没有帮助。

    继续您出色的第二条评论,您直截了当地告诉我,我 将无法使用匿名类解决“动态列”问题...这次您只是简单不正确。您真的应该在做出此类声明之前检查这些事情。为了证明我的方法有效,我举了一个简单快捷的例子:

    这是DataGrid

    <DataGrid Name="DataGrid" AutoGenerateColumns="True" />
    

    这是我定义我的匿名类型的地方,将它们放在ListBind 中,将它们放在DataGrid 中:

    var item = new { Id = 1, Name = "Bob", Age = 30 };
    var item2 = new { Id = 2, Name = "Jane", Age = 26 };
    var item3 = new { Id = 3, Name = "Dave", Age = 42 };
    var items = new[] { item, item2, item3 }.ToList();
    DataGrid.ItemsSource = items;
    

    然后您可以看到它运行良好。通过创建具有不同数量参数的类型来扩展此示例表明它可以与任意数量的列一起使用:

    var item = new { Id = 1, Name = "Bob", Age = 30, Date = DateTime.Now };
    var item2 = new { Id = 2, Name = "Jane", Age = 26, Date = DateTime.Now };
    var item3 = new { Id = 3, Name = "Dave", Age = 42, Date = DateTime.Now };
    var items = new[] { item, item2, item3 }.ToList();
    DataGrid.ItemsSource = items;
    

    当然,问题作者可以在循环中声明项目以提高效率。

    【讨论】:

    • 匿名类型不是在运行时创建的,而是编译器为您创建类型的简单语法糖。要在运行时创建类型,您要么需要即时编译它,要么使用类似dynamic 的东西。
    • @Martin,当我试图用最简单的术语向初学者解释一些复杂的编程概念时,是否值得真的选择所用语言的这种微小差异?在我看来,事实并非如此,因为在您发表评论后,问题作者并没有变得更聪明。此外,我添加了一个链接,以便他们可以了解关于使用 Microsoft 的匿名类型的所有,因此这里真的不需要 您的“帮助”,但谢谢。跨度>
    • 如果您发现我的评论“挑剔”,我很抱歉,但是您关于可以在运行时定义匿名类的说法是不正确的。虽然您建议使用DataGrid 是明智的,但您将无法使用匿名类解决“动态列”问题。无论是否初学者,匿名类在创建动态网格时都没有用。或者,如果我忽略了某些内容,您可以提供更详细的演示来说明如何做到这一点?
    • 对不起@MartinLiversage,但是不正确的。请参阅我的更新答案,了解与 your 陈述相矛盾的最简单示例。
    • @Sheridan:我想我会在这里遇到问题,因为我需要在运行时动态添加属性。在这种情况下,我知道我有 x 行和 y 列。所以我必须将 y 属性添加到每个 var 项中。所以即使有循环,我如何在运行时将 y 属性添加到 var 对象?我将跟进我正在研究的与您类似的逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多