i am writing xamarin forecast weather app with MVVM.
I fill ObservableCollection<DailyWeather> and ObservableCollection<HourlyWeather>.
In ViewModel
private ObservableCollection<DailyWeather> dailyWeather;
public ObservableCollection<DailyWeather> DailyWeather
{
get => dailyWeather;
set
{
dailyWeather = value;
OnPropertyChange();
}
}
Models
public class DailyWeather
{
public int DayOfYear { get; set; }
public ObservableCollection<HourlyWeather> HourlyWeather { get; set; }
}
public class HourlyWeather
{
public string Temperature { get; set; }
public string Time { get; set; }
}
Xaml code
<ListView ItemsSource="{Binding DailyWeather, Source={StaticResource vm}}"
RowHeight="200">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding DayOfYear}"/>
<ListView ItemsSource="{Binding HourlyWeather}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding Temperature}"/>
<Label Text="{Binding Time}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Parent ListView outputs collection and "DayOfYear".
Child ListView Outputs Collection and sees object properties "Temperature" and "Time" but not output them, why?
All collections are filled.
Why if i delete ViewCell from ListViews then app thow "specified cast is not valid" exception?
You need to remove this Source={StaticResource vm} from your binding.
Add this to your XAML:
<ContentPage.BindingContext>
<vm:VIEWMODEL></vm:VIEWMODEL>
</ContentPage.BindingContext>
And change parent listview to this:
<ListView ItemsSource="{Binding DailyWeather}" RowHeight="200">
Remove the Source={StaticResource vm} in ItemSource of your ListView. And set the code below in the code behind of your page.
this.BindingContext = this;
The whole code:
public partial class Page1 : ContentPage
{
private ObservableCollection<DailyWeather> dailyWeather;
public ObservableCollection<DailyWeather> DailyWeather
{
get => dailyWeather;
set
{
dailyWeather = value;
}
}
public Page1()
{
InitializeComponent();
DailyWeather = new ObservableCollection<DailyWeather>()
{
new DailyWeather()
{
DayOfYear=2011,
HourlyWeather=new ObservableCollection<HourlyWeather>()
{
new HourlyWeather()
{
Temperature="1",
Time="2011-01-02"
},
new HourlyWeather()
{
Temperature="2",
Time="2011-01-03"
},
new HourlyWeather()
{
Temperature="3",
Time="2011-01-04"
},
new HourlyWeather()
{
Temperature="4",
Time="2011-01-05"
}
}
}
};
this.BindingContext = this;
}
}
public class DailyWeather
{
public int DayOfYear { get; set; }
public ObservableCollection<HourlyWeather> HourlyWeather { get; set; }
}
public class HourlyWeather
{
public string Temperature { get; set; }
public string Time { get; set; }
}
Screenshot:
If you using mvvm , you should use Locator. Here is working example. Changed some tags because dont have WPF now at pc.
YourVM.cs
class YourVM : INotifyPropertyChanged
{
private ObservableCollection<DailyWeather> dailyWeather;
public ObservableCollection<DailyWeather> DailyWeather
{
get => dailyWeather;
set
{
dailyWeather = value;
OnPropertyChange(nameof(DailyWeather));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChange(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public YourVM()
{
DailyWeather = new ObservableCollection<DailyWeather>()
{
new DailyWeather()
{
DayOfYear=2011,
HourlyWeather=new ObservableCollection<HourlyWeather>()
{
new HourlyWeather()
{
Temperature="1",
Time="2011-01-02"
},
new HourlyWeather()
{
Temperature="2",
Time="2011-01-03"
},
new HourlyWeather()
{
Temperature="3",
Time="2011-01-04"
},
new HourlyWeather()
{
Temperature="4",
Time="2011-01-05"
}
}
}
};
}
}
MVVMLocator.cs
class MVVMLocator
{
public MVVMLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<YourVM>();
}
public static YourVM YourVM => SimpleIoc.Default.GetInstance<YourVM>();
}
App.xaml
<Application
x:Class="App2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App2">
<Application.Resources>
<ResourceDictionary>
<local:MVVMLocator x:Key="Locator"/>
</ResourceDictionary>
</Application.Resources>
</Application>
MainPage.xaml
<Page
x:Class="App2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<ListView ItemsSource="{Binding YourVM.DailyWeather , Source={StaticResource Locator}}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Height="200">
<TextBlock Text="{Binding DayOfYear}"/>
<ListView ItemsSource="{Binding HourlyWeather}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Temperature}"/>
<TextBlock Text="{Binding Time}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
Nuget: CommonServiceLocator , MvvmLightLibs
Related
I'm wrestling with these last few days. I found lots of links, but none of them really helped me. I'm quite a beginner in WPF.
All I need is to reach SelectedItem property in nested ListView.
Outter ListView binding works, of course.
What I tried after some research and doesn't work, even I don't really understand why it dosnt work:
<Window x:Class="ListViewRef.View.ListViewWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:ListViewRef.ViewModel"
xmlns:local="clr-namespace:ListViewRef.View"
mc:Ignorable="d"
Title="Nested List Views" Height="450" Width="800">
<Window.DataContext>
<vm:MainVM/>
</Window.DataContext>
<StackPanel x:Name="Global">
<TextBlock Text="{Binding MainTitle}"/>
<ListView ItemsSource="{Binding Path=SourceCollection}"
SelectedItem="{Binding Path=OutterSelectedItem}"
>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}"/>
<TextBlock Text="Now second ListView:"/>
<ListView ItemsSource="{Binding Strings}"
SelectedItem="{Binding Path=NestedSelectedItem,
RelativeSource={RelativeSource AncestorType=vm:MainVM},
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
></ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Window>
And ViewModel:
using ListViewRef.Model;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace ListViewRef.ViewModel
{
public class MainVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string mainTitle;
public string MainTitle {
get { return mainTitle; }
set { mainTitle = value; OnPropertyChanged(nameof(MainTitle)); }
}
private string nestedSelectedItem;
public string NestedSelectedItem {
get { return nestedSelectedItem; }
set
{
nestedSelectedItem = value;
MessageBox.Show("NestedSelectedItem: " + nestedSelectedItem);
OnPropertyChanged(nameof(NestedSelectedItem));
}
}
private string outterSelectedItem;
public string OutterSelectedItem {
get { return outterSelectedItem; }
set
{
outterSelectedItem = value;
MessageBox.Show("OutterSelectedItem: " + OutterSelectedItem);
OnPropertyChanged(nameof(OutterSelectedItem));
}
}
public ObservableCollection<ClassWithObsList> SourceCollection { get; set; }
public MainVM()
{
MainTitle = "Title of the Grid";
SourceCollection = new ObservableCollection<ClassWithObsList> {
new ClassWithObsList("First Title", new ObservableCollection<string> { "First", "Second"}),
new ClassWithObsList("Second Title", new ObservableCollection<string> { "Third", "Fourth"}),
new ClassWithObsList("Third Title", new ObservableCollection<string> { "Fifth", "Sixth"}),
};
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Model class:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace ListViewRef.Model
{
public class ClassWithObsList : INotifyPropertyChanged
{
private string title;
public string Title {
get { return title; }
set {
title = value;
OnPropertyChanged(nameof(Title));
}
}
public ObservableCollection<string> Strings { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public ClassWithObsList(string title, ObservableCollection<string> strings)
{
Title = title ?? throw new ArgumentNullException(nameof(title));
Strings = strings ?? throw new ArgumentNullException(nameof(strings));
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
In
SelectedItem="{Binding Path=NestedSelectedItem,
RelativeSource={RelativeSource AncestorType=vm:MainVM}, ...}
the type vm:MainVM is not an ancestor type of the inner ListView, because it not part of a visual or logical tree.
The AncestorType must be a UI element, e.g. the outer ListView. You would access the property by a nested property Path via its DataContext:
SelectedItem="{Binding Path=DataContext.NestedSelectedItem,
RelativeSource={RelativeSource AncestorType=ListView}, ...}
As a note, since you are not setting the View property of the ListViews, you could as well use the simpler base class ListBox instead of ListView:
<ListBox ItemsSource="{Binding Path=SourceCollection}"
SelectedItem="{Binding Path=OutterSelectedItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}"/>
<TextBlock Text="Now second ListView:"/>
<ListBox ItemsSource="{Binding Strings}"
SelectedItem="{Binding Path=DataContext.NestedSelectedItem,
RelativeSource={RelativeSource AncestorType=ListBox},
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I can not display the item list.
What am I doing wrong?
XAML(View):
<Grid.DataContext>
<vm:MainViewModel />
</Grid.DataContext>
<Grid.Resources>
<DataTemplate x:Key="Remedy">
<TextBlock Text="{Binding Titulo}" />
</DataTemplate>
<HierarchicalDataTemplate x:Key="Laboratorio"
ItemTemplate="{StaticResource Remedy}"
ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Titulo}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="Root"
ItemTemplate="{StaticResource Laboratorio}"
ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Titulo}" />
</HierarchicalDataTemplate>
</Grid.Resources>
<TreeView x:Name="dirR"
ItemsSource="{Binding Path=Arbol}"
ItemTemplate="{StaticResource Root}">
</TreeView>
C# (ViewModel):
class MainViewModel:INotifyPropertyChanged
{
private TreeItem _arbol = new TreeItem("Remedys");
public TreeItem Arbol
{
set
{
_arbol = value;
OnPropertyChanged("Arbol");
}
get { return _arbol; }
}
public MainViewModel()
{
//Populate Arbol
...
}
}
C# (Model):
public class TreeItem:INotifyPropertyChanged
{
private String _titulo;
private ObservableCollection<TreeItem> _items;
public String Titulo
{
get { return _titulo; }
set
{
_titulo = value;
OnPropertyChanged("Titulo");
}
}
public ObservableCollection<TreeItem> Items
{
get { return _items; }
set
{
_items = value;
OnPropertyChanged("Items");
}
}
public TreeItem(String __titulo)
{
Titulo = __titulo;
}
C# (MainWindow v1):
public MainWindow()
{
InitializeComponent();
}
C# (MainWindow v2) This version works ok but I do not like it because there is code dependency between View and Viewmodel
public MainWindow()
{
InitializeComponent();
MainViewModel vm = new MainViewModel();
dirR.Items.Add(vm.Arbol);
}
You can only bind a value to ItemsSource which implements IEnumerable. Generally spoken you have to bind a collection to ItemsSource.
Change your MainViewModel to
class MainViewModel:INotifyPropertyChanged
{
private ObservableCollection<TreeItem> _arbol =
new ObservableCollection<TreeItem>(
new List<TreeItem>
{
new TreeItem("Remedys")
} );
public ObservableCollection<TreeItem> Arbol
{
set
{
_arbol = value;
OnPropertyChanged("Arbol");
}
get { return _arbol; }
}
public MainViewModel()
{
//Populate Arbol
...
}
}
Set DataContext in MainWindow code:
From XAML:
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
From code:
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
Goal: I am trying to create a wrap panel that has children that are bound to an observable collection.
Current Expected Behavior: I expect to see 3 nested wrap panels that have an ellipse, a text block, a label and a checkbox.
Problem: My wrap panel and contents are not displayed at runtime. (Note: "Test" and "Test 2" Labels outside of the itemscontrol do display as expected.)
I have read this and it doesn't seem to solve my problem.
Code Behind
using MVVM_SandBox.Models;
using MVVM_SandBox.ViewModels;
namespace MVVM_SandBox
{
public partial class MainWindow
{
public MainViewModel VMMain = new MainViewModel();
public MainWindow()
{
VMMain.SomeItemModelBlahs = new System.Collections.ObjectModel.ObservableCollection<ItemModelBlah>() { new ItemModelBlah() { Label = "blah0" }, new ItemModelBlah() { Label = "blah1", CoolStuff = true }, new ItemModelBlah() { Label = "blah2" } };
InitializeComponent();
}
}
}
XAML
<Window x:Name="winMain" x:Class="MVVM_SandBox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewmodels="clr-namespace:MVVM_SandBox.ViewModels"
Title="MVVM SandBox" Height="600" Width="800" AllowDrop="True">
<Window.DataContext>
<viewmodels:MainViewModel></viewmodels:MainViewModel>
</Window.DataContext>
<StackPanel>
<Label Width="Auto" Height="Auto">Test</Label>
<ItemsControl ItemsSource="{Binding SomeItemModelBlahs}" Margin="10,10,10,10">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel x:Name="WrapPanelOfModelItems" Margin="10,10,10,10" Width="400" Height="200" IsItemsHost="True" MinWidth="200" MinHeight="200">
</WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Width="100" Height="100" Margin="10">
<Ellipse Width="10" Height="10" Fill="Aqua"></Ellipse>
<TextBlock Margin="10" Text="{Binding Label}"></TextBlock>
<Label>kjasdkjalsdjklsad</Label>
<CheckBox IsChecked="{Binding CoolStuff}">
<Label>Hello</Label>
</CheckBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Label Height="Auto" Width="Auto">Test 2</Label>
</StackPanel>
</Window>
View Model
using MVVM_SandBox.Models;
using System.Collections.ObjectModel;
namespace MVVM_SandBox.ViewModels
{
//[ImplementPropertyChanged]
public class MainViewModel
{
public ObservableCollection<ItemModelBlah> SomeItemModelBlahs { get; set; }
public MainViewModel()
{
}
}
}
Model
namespace MVVM_SandBox.Models
{
public class ItemModelBlah
{
public string Label { get; set; }
public bool CoolStuff { get; set; }
}
}
The code is creating two instances of MainViewModel: once in the code behind, and again in the XAML. The code behind instance has a non-null ObservableCollection, while the instance in the XAML is set as the DataContext.
I would suggest removing the viewmodels:MainViewModel from the XAML, and creating it solely in code:
public partial class MainWindow
{
public MainViewModel VMMain = new MainViewModel();
public MainWindow()
{
DataContext = VWMain;
InitializeComponent();
}
}
Also, it's a better design to set up the ObservableCollection from within the view model itself:
class MainViewModel
{
public ObservableCollection<ItemModelBlah> SomeItemModelBlahs { get; private set; }
public MainViewModel()
{
SomeItemModelBlahs = new ObservableCollection<ItemModelBlah>()
{
new ItemModelBlah() { Label = "blah0" },
new ItemModelBlah() { Label = "blah1", CoolStuff = true },
new ItemModelBlah() { Label = "blah2" }
};
}
}
I have a view model called FieldViewModel:
public class FieldViewModel: INotifyPropertyChanged
{
private Field m_field;
public Field FieldData
{
get { return m_field; }
set
{
m_field = value;
NotifyPropertyChanged("FieldData");
}
}
and the Field class:
public class Field : INotifyPropertyChanged
{
public List<string> SqlTypes
{
get { return Enum.GetNames(typeof(SqlDbType)).ToList(); }
}
private string m_FieldName = null;
public string FieldName
{
get { return m_FieldName; }
set
{
m_FieldName = value;
NotifyPropertyChanged("FieldName");
}
}
private string m_FieldType = null;
public string FieldType
{
get { return m_FieldType; }
set
{
m_FieldType = value;
NotifyPropertyChanged("FieldType");
}
}
private bool m_NullAllow = false;
public bool NullAllow
{
get { return m_NullAllow; }
set
{
m_NullAllow = value;
NotifyPropertyChanged("NullAllowsChecked");
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
The Xaml:
<ComboBox ItemsSource="{Binding FieldData.SqlTypes}" SelectionChanged="cmbField_Selected" Width="20" Height="20" Margin="5,5,0,5" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<TextBox Width="120" Height="20" Text="{Binding FieldType}" Margin="0,5" VerticalAlignment="Top" HorizontalAlignment="Left"/>
now in the xaml i want to bind the variables of the Field Class but i can't see them
I tried some thing but nothing works, if i put the variables of the Field Class inside the FieldViewModel it works good.
Thank for your help.
Here is an example which works for me:
<Window x:Class="DataGridExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="czesciTable" ItemsSource="{Binding model.list}"
AutoGenerateColumns="False"
CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
Viewmodel:
public class ViewModel
{
public Model model { get; set; }
public ViewModel()
{
model = new Model();
}
}
And model:
public class Model
{
public List<String> list { get; set; }
public Model()
{
list = new List<string>();
list.Add("Item1");
list.Add("Item2");
list.Add("Item3");
}
}
Result:
Or ComboBox:
<ComboBox ItemsSource="{Binding model.list}" VerticalAlignment="Top"/>
The code in the question was mainly correct. It was only missing the initialization of the Field Class.
I am using MVVM and trying to represent my ViewModel data in View.
I have a class called Track containing list of Variations. I want to represent each variation as a TextBlock using data binding.
I am able to represent a single track as:
<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>
I also have a class called TrackList containing collection of Tracks.
I tried to use HierarchicalDataTemplate to represent Hierarchical Data of TrackList.
But it's not working..
I am new to WPF, and I have tried the below things so far:
<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));
}
}
Please let me know for any farther information.
Thanks
I don't think you need HierarchicalDataTemplate, your tree has known number of levels (TrackList>Track>Variation). You can simply do this:
<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}" />
Where ItemsControl bind to Tracks property of the TrackList (ItemsControl.DataContext = TrackList).
You can represent your hierarchical data using a TreeView:
<TreeView ItemsSource="{Binding Tracks}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type src:Track}" ItemsSource="{Binding Vars}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>