如何在wpf中使用HierarchicalDataTemplate表示分层数据

时间:2014-01-09 11:22:16

标签: c# wpf data-binding mvvm

我正在使用MVVM并尝试在View中表示我的ViewModel数据。

我有一个名为Track的类,其中包含Variations列表。我想使用数据绑定将每个变体表示为TextBlock。

我能够将单个曲目表示为:

    <Window.Resources>
                <src:Track x:Key="trck"/>
                ...
    </Window.Resources>
    <StackPanel DataContext="{Binding Source={StaticResource trck}}" Orientation="Horizontal">
            <ItemsControl ItemsSource="{Binding Vars}" Height="53" Width="349">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Background="{Binding Path=color}" Height="15" Width="{Binding Path=elapsedtime}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
    </StackPanel>

我还有一个名为TrackList的类,其中包含Tracks的集合。 我尝试使用HierarchicalDataTemplate来表示TrackList的层次数据。 但它不起作用..

我是WPF的新手,到目前为止我已尝试过以下内容:

    <DockPanel.Resources>
        <DataTemplate DataType="{x:Type src:Variation}">
            <TextBlock Background="{Binding Path=color}" Height="15" Width="{Binding Path=elapsedtime}"/>
        </DataTemplate>

        <HierarchicalDataTemplate DataType = "{x:Type src:Track}" ItemsSource = "{Binding Path=Vars}">
            <StackPanel/>
        </HierarchicalDataTemplate>
    </DockPanel.Resources>

public class TrackList : ViewModel
    {
        private ICollection<Track> tracks;
        private Track selectedTrack;
        public string Name 
        { get; set; }

        public TrackList()
        {
            this.tracks = new List<Track>();
            this.tracks.Add(new Track("T1"));
            this.tracks.Add(new Track("T2"));
            Name = "Track List";
            selectedTrack = tracks.ElementAt(1);
        }

        public ICollection<Track> Tracks
        {
            get { return this.Tracks; }
            set { this.Tracks = value; }
        }

        public Track SelectedTrack
        {
            get { return this.selectedTrack; }
            set
            {
                if (this.selectedTrack != value)
                {
                    this.selectedTrack = value;
                    this.OnPropertyChanged("SelectedTrack");
                }
            }
        }
    }

public class Track : ViewModel
    {
        private ICollection<Variation> vars;
        private Variation selectedVar;
        public string Name { get; set; }

        public Track()
        {
            Init();
        }

        public Track(string p)
        {
            // TODO: Complete member initialization
            this.Name = p;
            Init();
        }

        private void Init()
        {
            this.vars = new List<Variation>();
            this.vars.Add(new Variation("var1", 20, Brushes.Red));
            this.vars.Add(new Variation("var2", 60, Brushes.Green));
            this.vars.Add(new Variation("var3", 40, Brushes.Khaki));
            this.vars.Add(new Variation("var4", 120, Brushes.Aqua));
            selectedVar = vars.ElementAt(1);
        }

        public ICollection<Variation> Vars
        {
            get { return this.vars; }
            set { this.vars = value; }
        }

        public Variation SelectedVar
        {
            get { return this.selectedVar; }
            set
            {
                if (this.selectedVar != value)
                {
                    this.selectedVar = value;
                    this.OnPropertyChanged("SelectedVar");
                }
            }
        }
    }

public class Variation : ViewModel
    {
        public int elapsedtime { get; set; }

        public string Name { get; set; }

        public System.Windows.Media.Brush color { get; set; }

        public Variation(string varname)
        {
            Name = varname;
        }

        public Variation(string name, int time, System.Windows.Media.Brush br)
        {
            // TODO: Complete member initialization
            this.Name = name;
            this.elapsedtime = time;
            this.color = br;
        }
    }

public abstract class ViewModel : INotifyPropertyChanged
    {
        private readonly Dispatcher _dispatcher;

        protected ViewModel()
        {
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected Dispatcher Dispatcher
        {
            get { return _dispatcher; }
        }

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChanged(this, e);
        }

        protected void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    }

如有任何进一步的信息,请告诉我。 谢谢

2 个答案:

答案 0 :(得分:0)

您可以使用TreeView代表您的分层数据:

<TreeView ItemsSource="{Binding Tracks}">
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type src:Track}" ItemsSource="{Binding Vars}">
            <TextBlock Text="{Binding Name}" />
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

答案 1 :(得分:0)

我认为你不需要HierarchicalDataTemplate,你的树有已知的级别数(TrackList&gt; Track&gt; Variation)。你可以这样做:

<DockPanel.Resources>
    <DataTemplate DataType="{x:Type src:Variation}">
        <TextBlock Background="{Binding Path=color}" Height="15" Width="{Binding Path=elapsedtime}"/>
    </DataTemplate>

    <DataTemplate DataType="{x:Type src:Track}">
        <StackPanel>
            <TextBlock Text="{Binding Name}"/>
            <ItemsControl ItemsSource="{Binding Vars}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </StackPanel>
    </DataTemplate>
</DockPanel.Resources>

<ItemsControl ItemsSource="{Binding Tracks}" />

其中ItemsControl绑定到TrackList的Tracks属性(ItemsControl.DataContext = TrackList)。