You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WPF中动态向WrapPanel添加预制Material Design Card?

动态添加预定义Material Design Card到WrapPanel的解决方案

嘿,我之前也碰到过一模一样的需求——不想在代码里手动拼所有子控件,只想把现成的Card像单个控件一样丢进WrapPanel里。这里有几个靠谱的方法,你可以根据自己的场景选:

方法1:把Card封装成UserControl(最推荐!)

这是最省心的方式,把你的Card做成独立的UserControl,之后用起来就和普通Button没区别:

  1. 创建UserControl
    新建一个UserControl(比如叫PDFThumbnailCard.xaml),把你的Card代码直接搬进去就行,我还给子控件加了名字方便后续操作:

    <UserControl x:Class="YourProjectNamespace.PDFThumbnailCard"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes">
        <materialDesign:Card Margin="3,3,0,0" Width="200">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="140" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <!-- 给Image加名字,方便后续设置预览图 -->
                <Image x:Name="PreviewImage" Height="140" Width="196" Stretch="UniformToFill" />
                <StackPanel HorizontalAlignment="Right" Grid.Row="2" Orientation="Horizontal" Margin="8">
                    <!-- 给Delete按钮加名字,方便绑定点击事件 -->
                    <Button x:Name="DeleteBtn" Style="{StaticResource MaterialDesignToolButton}" Width="30" Padding="2 0 2 0" materialDesign:RippleAssist.IsCentered="True">
                        <materialDesign:PackIcon Kind="Delete" />
                    </Button>
                </StackPanel>
            </Grid>
        </materialDesign:Card>
    </UserControl>
    
  2. 代码里动态添加
    现在你可以像实例化普通控件一样创建这个Card,然后直接丢进WrapPanel:

    // 新建一个Card实例
    var newPdfCard = new PDFThumbnailCard();
    // 给预览图设置图片源
    newPdfCard.PreviewImage.Source = new BitmapImage(new Uri("你的PDF预览图路径"));
    // 绑定删除按钮的点击事件
    newPdfCard.DeleteBtn.Click += (s, e) => { /* 这里写删除逻辑 */ };
    // 加到WrapPanel里
    yourWrapPanel.Children.Add(newPdfCard);
    

方法2:用XAML资源+克隆实例(不用新建UserControl)

如果你不想额外创建UserControl,也可以把Card作为资源,然后每次获取新实例添加:

  1. 在Resources里定义Card
    注意要加x:Shared="False",这样每次取资源都会返回新的实例,不会重复用同一个:

    <Window.Resources>
        <materialDesign:Card x:Key="PDFThumbnailTemplate" x:Shared="False" Margin="3,3,0,0" Width="200">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="140" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Image x:Name="PreviewImage" Height="140" Width="196" Stretch="UniformToFill" />
                <StackPanel HorizontalAlignment="Right" Grid.Row="2" Orientation="Horizontal" Margin="8">
                    <Button Style="{StaticResource MaterialDesignToolButton}" Width="30" Padding="2 0 2 0" materialDesign:RippleAssist.IsCentered="True">
                        <materialDesign:PackIcon Kind="Delete" />
                    </Button>
                </StackPanel>
            </Grid>
        </materialDesign:Card>
    </Window.Resources>
    
  2. 代码里获取并添加

    // 从资源里拿到新的Card实例
    var pdfCard = FindResource("PDFThumbnailTemplate") as MaterialDesignThemes.Wpf.Card;
    // 如果要修改子控件,比如设置预览图
    if (pdfCard?.FindName("PreviewImage") is Image previewImg)
    {
        previewImg.Source = new BitmapImage(new Uri("你的预览图路径"));
    }
    // 加到WrapPanel
    yourWrapPanel.Children.Add(pdfCard);
    

方法3:用ItemsControl绑定数据(批量添加更优雅)

如果你要一次性加很多Card,用MVVM的方式绑定数据会更清爽:

  1. 定义DataTemplate

    <Window.Resources>
        <DataTemplate x:Key="PDFThumbnailTemplate">
            <materialDesign:Card Margin="3,3,0,0" Width="200">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="140" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <!-- 绑定ViewModel里的预览图路径 -->
                    <Image Height="140" Width="196" Stretch="UniformToFill" Source="{Binding PreviewPath}" />
                    <StackPanel HorizontalAlignment="Right" Grid.Row="2" Orientation="Horizontal" Margin="8">
                        <!-- 绑定删除命令 -->
                        <Button Style="{StaticResource MaterialDesignToolButton}" Width="30" Padding="2 0 2 0" 
                                materialDesign:RippleAssist.IsCentered="True"
                                Command="{Binding DeleteCommand}" CommandParameter="{Binding}">
                            <materialDesign:PackIcon Kind="Delete" />
                        </Button>
                    </StackPanel>
                </Grid>
            </materialDesign:Card>
        </DataTemplate>
    </Window.Resources>
    
  2. 用ItemsControl替代手动添加
    把WrapPanel作为ItemsControl的布局容器,然后绑定数据源:

    <ItemsControl ItemsSource="{Binding YourPDFItemCollection}" ItemTemplate="{StaticResource PDFThumbnailTemplate}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
    

    之后你只需要在ViewModel里维护一个ObservableCollection<PDFItem>,往里面加数据,Card就会自动生成并显示在WrapPanel里啦。


内容的提问来源于stack exchange,提问作者Emre Kadan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:15:58