WPF:动态创建具有指定 x 行和 y 列的网格,每个单元格中都有静态图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20115742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:05:10  来源:igfitidea点击:

WPF : Dynamically create a grid with specified x rows and y columns with static image in each cell

c#wpfxaml

提问by simba

Question:I am new to WPF and i am not able to figure out this. How do i create a grid with x rows and y columns and insert image into each cell at run time ?

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

Scenario:I have an inventory project where the end user will search for a item and the application will specify where he can find the item. Now i am already retrieving the cabinet details where the items are kept which again have a rack of x rows and y columns . The rack being displayed can have different row or column sizes.See Image.

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

Approach:So what i figured out is that i should have a grid of x rows and y columns (known only at run time). Fill an image for each cell value. Insert a different image into the location of the item or highlight that cell value. But i am not able to find how to do that. Most of my searches point to add rows and columns dynamically. Am i missing something very obvious?

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

Expected Output:Given below is how i would like it to be displayed to my end user : Preview

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

采纳答案by simba

Like i said i was always wondering whether we need to go for a data grid in cases where we have static data. So this is what i came up with. I create a stack panel and add y images. Now i add x such stack panels. If the exact location of the image comes up i add a highlighted image. worked perfectly. Sharing code for any one who wants to reuse it.

就像我说的,我一直想知道在我们拥有静态数据的情况下是否需要使用数据网格。所以这就是我想出的。我创建了一个堆栈面板并添加了 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);
        }

    }

回答by Kumareshan

you can try come thing like this

你可以试试这样

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>

View Model

查看模型

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;
    }
}

回答by Sheridan

You can use a standard DataGridto do that. You can find out how to use one on the DataGrid Classpage on MSDN. Normally when using these controls, you would Binda collection of a custom data type class instances to the DataGrid.ItemsSourceproperty and the DataGridwould add a row for every item in the collection and a column for every property in the data type class.

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

As you want to have a variable number of columns, that would cause you a problem. However, there are something in .NET called Anonymous Typesthat you can use. This basically enables you to define an anonymous class at run time, so that you can define as many properties as you need columns. You can find out how to use them in the Anonymous Types (C# Programming Guide)page on MSDN.

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

My last hint for you is that you'd want to have stringproperties in your anonymous classes that provide the relevant image paths to use to display whatever image you want in each column. Then, you can declare a DataTemplateto define what each cell should look like (an Image)... for this to work, your stringfile paths will need to be in the following format -/YourAppName;component/YourImageFolderName/YourImageName.jpg:

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

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

You can find out more from the ItemsControl.ItemTemplatePropertyand Data Templating Overviewpages on MSDN.

您可以从MSDN 上的ItemsControl.ItemTemplate属性数据模板概述页面中找到更多信息。

Just in case that wasn't clear to anyone, I also added the link to the Anonymous Types (C# Programming Guide)page on MSDN, so that anyone that didn't understand could find out the whole story. Therefore, your first comment was unnecessary and helped nobody.

以防万一有人不清楚,我还在MSDN 上添加了匿名类型(C# 编程指南)页面的链接,以便任何不了解的人都可以找到整个故事。因此,您的第一条评论是不必要的,并且没有帮助任何人。

Moving on to your remarkable second comment where you flat out tell me that I will not be able to solve the "dynamic columns" problem using an anonymous class... this time you are just plain incorrect. You reallyshould check these things before you make such claims. To prove that my method works, I knocked up a quick and easy example:

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

Here is a DataGrid:

这是一个DataGrid

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

Here's where I define my anonymous type, put them in a Listand Bindthem to the DataGrid:

这是我定义匿名类型的地方,将它们放入 aList并将Bind它们放入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;

You can then see that it works perfectly well. Extending this example by creating a type with a different number of parameters shows that it would work with any number of columns:

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

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;

Of course the question author could declare the items in a loop to make it more efficient.

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