简体   繁体   中英

ListView with TreeViewItems in xaml

I'm pretty new to c#, the first thing that I'm trying to make is a ListView with data bindings which has turned out ok.

I'm now trying to make items have a twist button if the underlying model has any children (like the TreeView ). Each of the children will have columns the same as all the top level items.

How would I go about doing this? Is there an already existing control like this? If not would I be better off dressing up a TreeView to look like a ListView , or dress up a ListView to look like a TreeView ?

I went down the road outlined in this solution which dresses up a TreeView , but the end result looks pretty awful and the heading is actually just an item, so you lose all the nice column sizing and column buttons that can hook up to column sorting that you get in ListView so that route actually seems like it would be more work.

I noticed the new task manager has a control exactly like what I'm trying to create, I don't know how this made? probably in C though.

ListView与TreeView项目

Microsoft provides a sample that appears to be what you are looking for. A write-up of the example can be found here:

http://msdn.microsoft.com/en-us/library/vstudio/ms771523(v=vs.90).aspx

When you build and run the example you will end up with something resembling this:

在此输入图像描述

There is a large amount of templating done in the example, so you will be able to make things look the way you want.

It would probably be easier to Style the ListView , I had a quick play and managed to create a mockup in about 10min.

在此输入图像描述

Obviously you will want to add more to it, but it seems pretty easy to host a TreeView inside the ListView column.

Here is the mockup code if you want to use to build on.

Xaml:

<Window x:Class="WpfApplication8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="233" Width="405" Name="UI">
    <Grid DataContext="{Binding ElementName=UI}">
        <ListView ItemsSource="{Binding Processes}" >
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Process" Width="200"  >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel>
                                    <TreeView BorderThickness="0" ItemsSource="{Binding Processes}" >
                                        <TreeView.ItemTemplate>
                                            <HierarchicalDataTemplate ItemsSource="{Binding Processes}">
                                                <TextBlock Text="{Binding Name}" />
                                            </HierarchicalDataTemplate>
                                        </TreeView.ItemTemplate>
                                    </TreeView>
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="CPU" >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding CpuUsage, StringFormat={}{0} %}" TextAlignment="Right" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Memory" >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding MemUsage, StringFormat={}{0} MB}" TextAlignment="Right" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="VerticalContentAlignment" Value="Top" />
                </Style>
            </ListView.ItemContainerStyle>
        </ListView>
    </Grid>
</Window>

Code: sorry about the treeible mockup data loading :)

   public partial class MainWindow : Window
    {
        private ObservableCollection<ProcessInfo> _processes = new ObservableCollection<ProcessInfo>();

        public MainWindow()
        {
            InitializeComponent();
            Processes.Add(new ProcessInfo
            {
                CpuUsage = 10.3,
                MemUsage = 48.9,
                Processes = new ObservableCollection<Process>()
            });
            var pro = new Process{ Name = "Process1", Processes = new ObservableCollection<Process>()};
            pro.Processes.Add(new Process { Name = "SubProcess1", Processes = new ObservableCollection<Process>() });
            Processes[0].Processes.Add(pro);
            Processes.Add(new ProcessInfo
            {
                CpuUsage = 0,
                MemUsage = 100,
                Processes = new ObservableCollection<Process>()
            });
            var pro2 = new Process { Name = "Process2", Processes = new ObservableCollection<Process>() };
            pro2.Processes.Add(new Process { Name = "SubProcess1", Processes = new ObservableCollection<Process>() });
            pro2.Processes.Add(new Process { Name = "SubProcess2", Processes = new ObservableCollection<Process>() });
            pro2.Processes.Add(new Process { Name = "SubProcess3", Processes = new ObservableCollection<Process>() });
            Processes[1].Processes.Add(pro2);
        }

        public ObservableCollection<ProcessInfo> Processes
        {
            get { return _processes; }
            set { _processes = value; }
        }
    }

    public class ProcessInfo
    {
        public ObservableCollection<Process> Processes { get; set; }
        public double CpuUsage { get; set; }
        public double MemUsage { get; set; }
    }

    public class Process
    {
        public string Name { get; set; }
        public ObservableCollection<Process> Processes { get; set; }
    }

Good luck :)

What you describe sounds a bit like a TreeListView, and if you google 'WPF TreeListView' you will see some solutions that might be good for you. I have used one from Telerik , but it might be overkill depending on how complicated your needs are.

If you only want one sub-level like the image you attached, you might want to just roll your own using a ListView with a complex DataTemplate for the first column which would show an expander button and a simple ListBox bound to the children items.

Similar to the answer here , except your cell would have a checkbox styled to look like the arrow, the text for the item, and a child ListBox. Then bind the visibility of the child ListBox to the state of the checkbox.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM