wpf 使用带有子类列表的类的Treeview的ItemContainerStyle

1mrurvl1  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(130)

我的ObservableCollection来自类型FUClass。在这个类中是一个FUSubClass的List。ListView Itemsource绑定到ObservableCollection FUList。
My TreeView显示GroupName,a有一个TreeViewItem和ItemName。
问题是,只有1个TreeViewItem与所有项目从FUSubClassList显示,但我想为每个项目一个TreeViewItem。不知道如何实现在ItemContainerStyle。

XAML ItemContainerStyle:

<Style PresentationOptions:Freeze="True" TargetType="{x:Type ListViewItem}">
        <Setter Property="Height" Value="Auto" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListViewItem}">
                    <TreeView Width="1248" MinHeight="50">
                        <TreeViewItem>
                            <TreeViewItem.Header>
                                <StackPanel Orientation="Horizontal">
                                    <ContentPresenter Content="{Binding GroupName}" RecognizesAccessKey="False" />
                                </StackPanel>
                            </TreeViewItem.Header>
                            <TreeViewItem ItemsSource="{Binding FUSubClassList}">
                                <TreeViewItem.Header>
                                    <Grid>
                                        <ContentPresenter Content="{Binding ItemName}" RecognizesAccessKey="False" />
                                    </Grid>
                                </TreeViewItem.Header>
                            </TreeViewItem>
                        </TreeViewItem>
                    </TreeView>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

字符串

C#

public class FUClass : INotifyPropertyChanged
    {
        private string groupName;
        public string GroupName
        {
            get { return this.groupName; }
            set
            {
                if (this.groupName != value)
                {
                    this.groupName = value;

                    this.OnPropertyChanged(nameof(GroupName));
                }
            }
        }
        private ObservableCollection<FUSubClass> FUSubClassList = new ObservableCollection<FUSubClass>();
        public ObservableCollection<FUSubClass> FUSubClassList
        {
            get { return FUSubClassList; }
            set { FUSubClassList = value; }
        }

        public class FUSubClass : INotifyPropertyChanged
        {   
            private string itemName;
            public string ItemName
            {
                get { return this.itemName; }
                set
                {
                    if (this.itemName != value)
                    {
                        this.itemName = value;

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

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

    private ObservableCollection<FUClass> FUList = new ObservableCollection<FUClass>();

用户界面


的数据

r6vfmomb

r6vfmomb1#

跳过ItemContainerStyle并为您的数据类型定义数据模板,例如:

<TreeView ItemsSource="{Binding FUList}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:FUClass}" ItemsSource="{Binding FUSubClassList}">
            <TextBlock Text="{Binding GroupName}" />
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type local:FUSubClass}">
            <TextBlock Text="{Binding ItemName}" />
        </DataTemplate>
    </TreeView.Resources>
</TreeView>

字符串

vlju58qv

vlju58qv2#

所以,我要做的第一件事是创建一个基类,父类/子类可以继承它。我称之为FUBase,但它看起来像这样:

public abstract class FUBase : INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            SetField(ref _name, value);
        }
    }

    protected FUBase(string name)
    {
        Name = name;
    }

    protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        Debug.Assert(!string.IsNullOrEmpty(propertyName));

        if (EqualityComparer<T>.Default.Equals(field, value)) 
        {
            return false;
        }

        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }

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

字符串
然后,父类(我称之为FUGroup)和实际的项类(名为FUItem)看起来像这样:

public class FUGroup : FUBase
{
    public ObservableCollection<FUBase> Items { get; set; } = new ();

    public FUGroup(string name) : base(name)
    {

    }
}

public class FUItem : FUBase
{
    public FUItem(string name) : base(name)
    {

    }
}


注意FUGroup类有一个ObservableCollection<FUBase>?它允许你在每个FUGroup中包含FUGroupFUItem对象。在我做的测试应用程序中,我就是这样存储顶级ObservableCollection<FUBase>的(我在MainWindowViewModel中称之为Items)。

public ObservableCollection<FUBase> Items { get; set; }

public MainWindowViewModel()
{
    Items = new ()
    {
        new FUGroup("Group 1")
        {
            Items = new ()
            {
                new FUGroup("Group 1-2")
                {
                    Items = new ()
                    {
                        new FUItem("Item 1"),
                        new FUItem("Item 2"),
                        new FUItem("Item 3")
                    }
                },
                new FUItem("Item 4")
            }
        },
        new FUGroup("Group 2")
        {
            Items = new ()
            {
                new FUItem("Item 5")
            }
        }
    };
}


在此之后,您需要的最后一件事是DataTemplates。我只是把它们放在TreeView的资源中,但您可以把它们扔到ResourceDictionary或任何父FrameworkElement中。

<TreeView ItemsSource="{Binding Items}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type models:FUGroup}" ItemsSource="{Binding Items}">
            <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type models:FUItem}">
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </TreeView.Resources>
</TreeView>


结果:
x1c 0d1x的数据

相关问题