在运行时动态创建多个 UI 元素 - C# WPF

Posted

技术标签:

【中文标题】在运行时动态创建多个 UI 元素 - C# WPF【英文标题】:Creating multiple UI Elements dynamically during runtime - C# WPF 【发布时间】:2015-10-08 14:59:00 【问题描述】:

我对 C# 和 WPF 还很陌生,但我开始构建一个应用程序,它应该具有列出项目的功能和一些细节。目前看起来像

这些“项目”的数据(一个项目是包含在边框中的多个标签(稍后我也想添加图片))是通过 REST 服务加载的,我不知道如何许多项目将得到回应。现在,由于收到的项目数量不同,我无法在 xaml 中静态创建标签。

我的问题是,如何以编程方式创建多个标签(以及边框和图像),在窗口中正确对齐它们并处理标签以用数据填充它们?

非常感谢您的帮助!

【问题讨论】:

我认为您在使用ItemsControl 之后。还有一个不错的教程here 可能会有所帮助。我没有回答,因为在 SO 上有很多 ItemsControl 的示例用法。希望这只会将您推向正确的方向。 你能显示来自 REST 服务的 Json 响应对象吗?您将需要使用反射来创建控件。在窗口中正确对齐它们并用数据填充标签将取决于您从服务调用返回的结构。 感谢您的帮助 Yoink,我认为 ListBox(稍后在您链接的教程中)或 ItemsControl 与我正在寻找的相似! @Bobby API 的链接和我正在使用的响应:link 我明白了。标签的数量不会变化; REST 调用返回的“边界绑定项目”的数量是可变的。你会的;那时不需要反思。我会发布一个答案,可能会为您指明正确的方向。 是的,没错!我本来可以更好的措辞,谢谢! 【参考方案1】:

正如您在评论中指出的那样,ListBox 可能适合您的目的。一般的想法是,您希望通过ItemTemplate 指定ListBox 的格式,并在ItemTemplate 中指定DataTemplate,其中包含支持您的API 数据的必要控件,并指定绑定到映射的模型来自 JSON。 XAML 的不完整示例:

<ListBox x:Name="transactionsListBox">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="Black" BorderThickness=".5" Padding="1">
                <StackPanel>
                    <Label x:Name="id" Content="Binding Path=Id" />
                    <Label x:Name="item_id" Content="Binding Path=Item_Id" />
                    <Label x:Name="price" Content="Binding Path=Price" />
                    <Label x:Name="quantity" Content="Binding Path=Quantity" />
                    <Label x:Name="created" Content="Binding Path=Created" />
                    <Label x:Name="purchased" Content="Binding Path=Purchased" />
                </StackPanel>
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

上述绑定的 Path= 属性需要与您创建的模型的属性名称相匹配,以存储来自 REST 调用的事务。然后,当您拥有该模型类型的列表的实例时,您的代码会想要执行以下操作:

List<Transaction> myTransactions = apiCall.response.mapToMyModel() // pseduocode
transactionsListBox.DataContext = myTransactions;

【讨论】:

我省略了您请求的图像部分,但它是 XAML 中定义为该 StackPanel 子项的控件的简单扩展。 另外,如果您想更好地控制这些标签的显示,您可以选择使用 Grid 而不是 StackPanel,并自定义 Grid 的列以满足您的显示需要。 StackPanel 也应该有Orientation="Horizontal" 非常感谢,效果很好(感谢Orientation="Horizontal" 的提示!但是我还有一个问题,tlb.DataContexttlb.ItemsSource 之间有什么区别,因为在这种情况下它仅适用于tlb.ItemsSource DataContext 就像是在说“这是我们将要处理的对象类型”,而ItemsSource 是在说“这是我希望迭代的内容列表”【参考方案2】:

为了补充 Bobby 的答案,这里有一个使用 ItemsControl 的示例。

<ItemsControl ItemsSource="Binding SellTransactions">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <Label Grid.Column="0" Content="Binding created"></Label>
                <Label Grid.Column="1" Content="Binding id"></Label>
                <Label Grid.Column="2" Content="Binding item_id"></Label>
                <Label Grid.Column="3" Content="Binding price"></Label>
                <Label Grid.Column="4" Content="Binding purchased"></Label>
                <Label Grid.Column="5" Content="Binding quantity"></Label>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

事务的类:

public class SellTransaction

    public long id  get; set; 
    public int item_id  get; set; 
    public int price  get; set; 
    public int quantity  get; set; 
    public DateTime created  get; set; 
    public DateTime purchased  get; set; 

【讨论】:

非常感谢您的意见!我将使用一个类似于您在 ListBox 中制作的网格! :)

以上是关于在运行时动态创建多个 UI 元素 - C# WPF的主要内容,如果未能解决你的问题,请参考以下文章

wpf 动态更新 UI 而不会冻结 UI

wpf怎么动态 控制控件位置c#代码

多线程任务更新 1 个进度条 - UI C# WPF

使用给定的搜索参数 Wpf UI 测试无法在页面上找到元素

WPF C#为动态创建的按钮创建Click事件

WPF 如何将主题应用于使用 MVVM 动态创建的对象