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

如何在C#后台代码中动态创建数据模板并绑定TreeView层级数据

动态创建TreeView数据模板与层级数据绑定解决方案

Great start with your DataTemplate code! The key missing pieces here are using a HierarchicalDataTemplate instead of a regular DataTemplate (since TreeView handles nested/hierarchical data) and properly binding the child items collection for each node. Let's break this down step by step:

1. 替换为HierarchicalDataTemplate

TreeView items depend on HierarchicalDataTemplate to manage nested child nodes—this template includes an ItemsSource property that lets you bind to the child collection of each parent node. Here's how to adjust your template creation code:

private HierarchicalDataTemplate GetHierarchicalTreeTemplate()
{
    // Use HierarchicalDataTemplate instead of basic DataTemplate
    var hierarchicalTemplate = new HierarchicalDataTemplate();

    // Create root StackPanel (same as your original setup)
    var stackPanel = new FrameworkElementFactory(typeof(StackPanel));
    stackPanel.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);

    // --- Fix CheckBox Binding ---
    // Bind IsChecked to a boolean property on your data model (e.g., IsSelected)
    var checkBox = new FrameworkElementFactory(typeof(CheckBox));
    checkBox.SetValue(CheckBox.MarginProperty, new Thickness(2));
    // Use TwoWay binding so UI changes update your data model and vice versa
    checkBox.SetBinding(CheckBox.IsCheckedProperty, new Binding("IsSelected") { Mode = BindingMode.TwoWay });
    // Optional: Bind Tag to the node's Name for reference in logic
    checkBox.SetValue(CheckBox.TagProperty, new Binding("Name"));
    stackPanel.AppendChild(checkBox);

    // --- Image Binding (your original code works well) ---
    var image = new FrameworkElementFactory(typeof(Image));
    image.SetValue(Image.MarginProperty, new Thickness(2));
    image.SetBinding(Image.SourceProperty, new Binding("ImageUrl"));
    stackPanel.AppendChild(image);

    // --- TextBlock with ToolTip Binding ---
    var textBlock = new FrameworkElementFactory(typeof(TextBlock));
    textBlock.SetBinding(TextBlock.TextProperty, new Binding("Name"));
    // Bind ToolTip to the node's Name (or another property like Description if needed)
    textBlock.SetBinding(TextBlock.ToolTipProperty, new Binding("Name"));
    stackPanel.AppendChild(textBlock);

    // Assign the visual tree to the template
    hierarchicalTemplate.VisualTree = stackPanel;

    // --- Critical: Bind child items collection ---
    // Replace "Children" with the name of the child collection property on your data model
    hierarchicalTemplate.ItemsSource = new Binding("Children");

    return hierarchicalTemplate;
}

2. 定义你的数据模型

You need a data model class that represents each TreeView node, including a collection for child nodes. Make sure it implements INotifyPropertyChanged so UI updates reflect data changes:

public class TreeNodeModel : INotifyPropertyChanged
{
    private string _name;
    private string _imageUrl;
    private bool _isSelected;
    private ObservableCollection<TreeNodeModel> _children;

    public string Name
    {
        get => _name;
        set { _name = value; OnPropertyChanged(); }
    }

    public string ImageUrl
    {
        get => _imageUrl;
        set { _imageUrl = value; OnPropertyChanged(); }
    }

    public bool IsSelected
    {
        get => _isSelected;
        set { _isSelected = value; OnPropertyChanged(); }
    }

    public ObservableCollection<TreeNodeModel> Children
    {
        get => _children;
        set { _children = value; OnPropertyChanged(); }
    }

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

3. 绑定TreeView数据源并应用模板

Finally, connect the dynamic template to your TreeView and set its ItemsSource to your root node collection:

private void InitializeTreeView()
{
    // Create sample hierarchical data
    var rootNodes = new ObservableCollection<TreeNodeModel>
    {
        new TreeNodeModel
        {
            Name = "Root Folder 1",
            ImageUrl = "/Icons/folder.png",
            IsSelected = false,
            Children = new ObservableCollection<TreeNodeModel>
            {
                new TreeNodeModel { Name = "Document 1.1", ImageUrl = "/Icons/file.png" },
                new TreeNodeModel { Name = "Document 1.2", ImageUrl = "/Icons/file.png" }
            }
        },
        new TreeNodeModel { Name = "Root Folder 2", ImageUrl = "/Icons/folder.png" }
    };

    // Apply the dynamic template to the TreeView
    BimTreeView.ItemTemplate = GetHierarchicalTreeTemplate();

    // Bind the root data collection to the TreeView
    BimTreeView.ItemsSource = rootNodes;
}

额外小贴士

  • XamlReader Alternative: For newer .NET versions, Microsoft recommends using XamlReader.Parse to create templates—it's more readable than FrameworkElementFactory. Here's a quick example:
    private HierarchicalDataTemplate GetTemplateViaXamlReader()
    {
        var xaml = @"
            <HierarchicalDataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
                                      ItemsSource='{Binding Children}'>
                <StackPanel Orientation='Horizontal'>
                    <CheckBox Margin='2' IsChecked='{Binding IsSelected, Mode=TwoWay}' Tag='{Binding Name}'/>
                    <Image Margin='2' Source='{Binding ImageUrl}'/>
                    <TextBlock Text='{Binding Name}' ToolTip='{Binding Name}'/>
                </StackPanel>
            </HierarchicalDataTemplate>";
        return (HierarchicalDataTemplate)XamlReader.Parse(xaml);
    }
    

内容的提问来源于stack exchange,提问作者Ali Asad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:08:43