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

WPF中基于数据库记录数动态生成Material Design卡片的技术实现问询

WPF中基于数据库记录数动态生成Material Design卡片的技术实现问询

嘿,我完全懂你现在的需求啦——你想让WPF界面里的Material Design卡片能跟着数据库里的记录数量自动生成,每张卡片对应一条数据,把数据库里的图片和文本都显示出来对吧?别担心,咱们一步步来搞定这个问题:

第一步:先定义对应数据库记录的数据模型

首先得创建一个类来映射数据库里的每条记录,这样咱们才能把数据库的数据转换成WPF能识别的对象。这个类需要实现INotifyPropertyChanged接口,这样数据更新时界面能自动同步:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Media;

public class CardItem : INotifyPropertyChanged
{
    private string _title;
    private string _description;
    private ImageSource _imageSource;

    public string Title
    {
        get => _title;
        set
        {
            _title = value;
            OnPropertyChanged();
        }
    }

    public string Description
    {
        get => _description;
        set
        {
            _description = value;
            OnPropertyChanged();
        }
    }

    public ImageSource ImageSource
    {
        get => _imageSource;
        set
        {
            _imageSource = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

第二步:在ViewModel里准备数据集合

接下来需要一个能自动通知界面变化的集合(推荐用ObservableCollection<T>)来存放所有从数据库读取的卡片数据,然后写个方法把数据库里的记录转换成CardItem对象加进去:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Media.Imaging;
using System;

public class MainViewModel : INotifyPropertyChanged
{
    public ObservableCollection<CardItem> CardItems { get; set; }

    public MainViewModel()
    {
        CardItems = new ObservableCollection<CardItem>();
        // 初始化时加载数据库数据
        LoadCardDataFromDatabase();
    }

    private void LoadCardDataFromDatabase()
    {
        // 这里替换成你实际的数据库查询逻辑
        // 示例:假设你已经有方法从数据库获取记录列表
        var dbRecords = GetRecordsFromDatabase();
        
        foreach (var record in dbRecords)
        {
            var cardItem = new CardItem
            {
                Title = record.Title,
                Description = record.Description,
                // 如果数据库存的是图片路径,直接转成ImageSource
                ImageSource = new BitmapImage(new Uri(record.ImagePath, UriKind.RelativeOrAbsolute))
            };
            CardItems.Add(cardItem);
        }
    }

    // 你需要自己实现这个方法,从数据库读取记录
    private IEnumerable<YourDbRecordType> GetRecordsFromDatabase()
    {
        // 这里写你的数据库查询代码,比如用EF Core或者ADO.NET
        // 返回数据库里的记录集合
    }

    // 实现INotifyPropertyChanged接口,和上面CardItem的逻辑一样
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

第三步:修改XAML,用ItemsControl动态生成卡片

你原来的代码是手动写了一堆重复的Card,现在咱们把这些手动代码换成ItemsControl,让它自动根据集合里的CardItem生成卡片:

<StackPanel Grid.Row="1">
    <hc:SearchBar
        hc:InfoElement.Placeholder="Search"
        hc:InfoElement.TitlePlacement="Left"
        Style="{StaticResource SearchBarExtend}"
        Margin="20 0 125 20"
        />
    <materialDesign:Card Margin="20 0 125 20">
        <StackPanel>
            <TextBlock
                Text="Categories"
                FontSize="28"
                FontWeight="400"
                />
            <TextBlock
                Text="Самые распространенные и часто выбираемые архитекрурные решения зданий"
                FontSize="14"
                FontWeight="200"
                />
            <hc:ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden" IsInertiaEnabled="True">
                <!-- 用ItemsControl绑定CardItems集合 -->
                <ItemsControl ItemsSource="{Binding CardItems}">
                    <!-- 指定卡片的布局容器为WrapPanel -->
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapPanel Orientation="Horizontal" Margin="0 20 0 0"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <!-- 定义单张卡片的模板,绑定CardItem的属性 -->
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <materialDesign:Card Margin="15 0 15 0 ">
                                <StackPanel Height="200" Width="200">
                                    <Image Source="{Binding ImageSource}"/>
                                    <TextBlock
                                        FontSize="18"
                                        FontWeight="Medium"
                                        Text="{Binding Title}"
                                        />
                                    <TextBlock
                                        FontSize="15"
                                        FontWeight="Regular"
                                        Text="{Binding Description}"
                                        />
                                </StackPanel>
                            </materialDesign:Card>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </hc:ScrollViewer>
        </StackPanel>
    </materialDesign:Card>
</StackPanel>

第四步:关联ViewModel和View

最后要把ViewModel设置为界面的DataContext,这样XAML里的绑定才能生效。比如在Window的构造函数里:

public MainWindow()
{
    InitializeComponent();
    // 设置DataContext为ViewModel实例
    DataContext = new MainViewModel();
}

额外注意点

  • 如果数据库里存储的是图片的二进制数据(不是路径),需要把byte[]转换成ImageSource,示例代码如下:
// 假设record.ImageData是数据库里的二进制图片
byte[] imageBytes = record.ImageData;
using (var ms = new MemoryStream(imageBytes))
{
    var bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    bitmap.StreamSource = ms;
    bitmap.EndInit();
    cardItem.ImageSource = bitmap;
}
  • 确保你的XAML顶部已经正确引用了Material Design和HandyControl的命名空间:
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:hc="https://handyorg.github.io/handycontrol"

备注:内容来源于stack exchange,提问作者Fainer Game

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 14:07:38