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>
Related
Im using WPF with MVVM design-patern, and I need to bind a command which is of a ItemsSource binding parent :
View :
<Window x:Class="TaskSupervisor.MainWindow"
...
...>
<Window.DataContext>
<local:TacheGroupeViewModel/>
</Window.DataContext>
<Grid>
<TreeView x:Name="TachesTree" ItemsSource="{Binding TachesGroupes.GroupesConfig}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Value.Tasks}">
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<Grid>
<CheckBox x:Name="InProgress"
IsChecked="{Binding ModifInProgress}">
</CheckBox>
<StackPanel Grid.Row="2" Grid.Column="2" Orientation="Horizontal">
...
</StackPanel>
<StackPanel Grid.Row="3" Grid.Column="2" Orientation="Horizontal">
...
</StackPanel>
</Grid>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
<TextBlock Text="{Binding Value.DisplayGroupe, Mode=OneWay}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
ViewModel :
class TacheGroupeViewModel : INotifyPropertyChanged {
public Model.TachesGroupes TachesGroupes { get; set; }
public TacheGroupeViewModel() {
this.TachesGroupes = new Model.TachesGroupes();
// return a Dictionary<string, CustomClass> Object
// CustomClass => Contain some field and a List Of custom class
}
private ICommand _cmdEnCoursDeTraitement;
public ICommand CmdEnCoursDeTraitement {
get {
return _cmdEnCoursDeTraitement ?? ( _cmdEnCoursDeTraitement = new RelayCommand(x => {Test(); }) );
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void Test() {
var test = "xD";
}
}
I want to make a bind on my Checkbox object : How can I do this while the Items source of the HierarchicalDataTemplate is set to "Tasks" I can only binding on my "Tasks" filds.
How can get the parent of the ItemSource ?
instead of finding the right parent and view model...I had a Forward pattern mainly for context menu...
All my view model have this command
private ICommand forwardCommand;
public ICommand ForwardCommand
{
get
{
if (forwardCommand == null)
forwardCommand = new RelayCommand<string>(
delegate(string param)
{
Messenger.Default.Send<CommandContext>(GetForwardCommandContext(param),
ViewModelBaseMessages.ContextCommand );
},
delegate(string param)
{
return CanForwardCommand(param);
});
return forwardCommand;
}
}
it is then forwarded to the view model that have registered to a forward_message
Messenger.Default.Register<CommandContext>(this, ViewModelBaseMessages.ContextCommand,
(CommandContext o) =>
{
ExecuteDistantCommand( o );
} );
you can find this code in my project on github
please, use a mvvm nuget like mvvmlight and do not invent the wheel...;-)
Ok, I tried it several ways, but none worked as it should be in my case. I have a simple Window with a single ComboBox. I am changing the code to MVVM, so now everything is still in the Code-Behind and should go to a ViewModel, etc.
But even on the first step (binding the ViewModel to the View/Window) I don't seem to be able to bind them together.
My Window XAML:
<Window x:Class="CustomerGuidance.ClientWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:VM="clr-namespace:CustomerGuidance.ViewModels"
Title="Stop'n'Go - Client" Height="22" Width="229"
Loaded="ClientWindow_OnLoaded" WindowStyle="None"
WindowStartupLocation="Manual" Top="0" Left="0"
ResizeMode="NoResize" ShowInTaskbar="False" Topmost="True">
<Window.DataContext>
<VM:EmployeeViewModel />
</Window.DataContext>
<Canvas Background="Gainsboro">
<ComboBox Name="EmployeesComboBox"
ItemsSource="{Binding EmployeeEntries}"
Width="192" FontFamily="Arial" FontSize="14">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Lastname}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding Surname}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Canvas>
The ViewModel looks like this:
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace CustomerGuidance.ViewModels
{
public class EmployeeViewModel : INotifyPropertyChanged
{
public EmployeeViewModel()
{
}
public static ObservableCollection<ServerWindow.EmployeeEntry> EmployeeEntries { get; set; } = new ObservableCollection<ServerWindow.EmployeeEntry>();
private string _surname;
private string _lastname;
private int _id;
public string Surname
{
get { return _surname; }
set
{
if (_surname == value)
return;
_surname = value;
NotifyPropertyChanged("Surname");
}
}
public string Lastname
{
get { return _lastname; }
set
{
if (_lastname == value)
return;
_lastname = value;
NotifyPropertyChanged("Lastname");
}
}
public int Id
{
get { return _id; }
set
{
if (_id == value)
return;
_id = value;
NotifyPropertyChanged("Id");
}
}
public virtual event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I get the following error message: "The Name "EmployeeViewModel" is not available in the namespace "clr-namespace:CustomerGuidance.ViewModels".And now the question: What am I missing? How can I bind the ViewModel to my window-XAML?
You should build your code for the errors to disappear.
It's because the namespace is not yet available in the assembly the designer relies on (your program) before it has been built.
Problem
I am trying to bind a ComboBox's SelectedItem to a custom class but this does not update when the property is changed.INotifyPropertyChanged is implemented.
The DataContext
The DataContext is a custom class which contains many properties, but an extract of this is below. You can see it implements INotifyPropertyChanged and this called when the two properties are changed.
public class BctsChange : INotifyPropertyChanged
{
#region declarations
private byContact _Engineer;
public byContact Engineer
{
get { return _Engineer; }
set
{
_Engineer = value;
NotifyPropertyChanged("Engineer");
OnEngineerChanged();
}
}
private BctsSvc.DOSets _LeadingSet;
public BctsSvc.DOSets LeadingSet
{
get { return _LeadingSet; }
set { _LeadingSet = value; NotifyPropertyChanged("LeadingSet"); }
}
#endregion
#region INotify
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public BctsChange()
{
Engineer = new byContact(Environment.UserName);
}
private void OnEngineerChanged()
{
if (Engineer != null)
{
BctsSvc.DOSets leadSet = GetLeadingSetFromDeptCode(Engineer.DeptCode);
if (leadSet == null) return;
LeadingSet = leadSet;
}
}
private static BctsSvc.DOSets GetLeadingSetFromDeptCode(string DeptCode)
{
BctsSvc.BctsServiceSoapClient svc = new BctsSvc.BctsServiceSoapClient();
BctsSvc.DOSets setX = svc.GetSetFromDeptCode(DeptCode);
return setX;
}
}
The Window XAML
I have several controls on the window, but to keep the code simple I believe the following extract will suffice.
<Window x:Class="MyNamespace.wdSubmit"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:MyNamespace"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Name="ucReqForm"
Title="wdSubmit" >
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch">
<GroupBox Header="Engineer Details" Name="grpOwnerDetails" >
<StackPanel Orientation="Vertical">
<Grid VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="35"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Engineer.FullName, FallbackValue='Please select an engineer by clicking →', Mode=OneWay}" Margin="5,0" IsEnabled="True" FontStyle="Italic" />
<Button Content="{StaticResource icoSearch}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Grid.Column="1" Height="23" Name="btnSelectEngineer" Margin="0,0,5,0" HorizontalAlignment="Stretch" ToolTip="Search for an engineer responsible" Click="btnSelectEngineer_Click" />
</Grid>
<ComboBox Height="23" x:Name="ddSet2" Margin="5,0" ItemsSource="{Binding LeadingSets, Mode=OneWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" SelectedItem="{Binding LeadingSet, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,NotifyOnTargetUpdated=True}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding SetName}" ToolTip="{Binding HelpInfo}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<my:LabelledDropdown Height="23" x:Name="ddSet" Margin="5,0" ItemsSource="{Binding LeadingSets, Mode=OneWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" SelectedItem="{Binding LeadingSet, Mode=TwoWay,NotifyOnTargetUpdated=True,NotifyOnSourceUpdated=True}" Label="e.g. BodyHardware">
<my:LabelledDropdown.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding SetName}" ToolTip="{Binding HelpInfo}"/>
</DataTemplate>
</my:LabelledDropdown.ItemTemplate>
</my:LabelledDropdown>
</StackPanel>
</GroupBox>
</StackPanel>
</Window>
The above extract contains:
A Label that contains a contact's name, and a button to search for a contact, bound to the FullName of the Engineer
A ComboBox that contains departments within the company, bound to an ObservableCollection<DOSets>, which contains a list of departments
Two ComboBoxes, one which is a custom one and the other which is temporary to ensure the bug is not within the control. These are Databound to LeadingSet
Window Code Behind
In the code behind I set the DataContext to CurrentChange. When the user wants to select a different Engineer then this will update the selected department for the engineer in CurrentChange.
When the user changes the engineer, the data binding for the engineer is updated, but the selected department (Leading Set) isn't.
//Usings here
namespace MyNamespace
{
public partial class wdSubmit : Window, INotifyPropertyChanged
{
private BctsSvc.BctsServiceSoapClient svc;
private BctsChange _CurrentChange;
public BctsChange CurrentChange
{
get { return _CurrentChange; }
set { _CurrentChange = value; OnPropertyChanged("CurrentChange"); }
}
private List<BctsSvc.DOSets> _LeadingSets;
public List<BctsSvc.DOSets> LeadingSets
{
get
{
return _LeadingSets;
}
}
public wdSubmit()
{
InitializeComponent();
svc = new BctsSvc.BctsServiceSoapClient();
_LeadingSets = svc.GetLeadSets().ToList();
OnPropertyChanged("LeadingSets");
this._CurrentChange = new BctsChange();
this.DataContext = CurrentChange;
CurrentChange.PropertyChanged += new PropertyChangedEventHandler(CurrentChange_PropertyChanged);
}
void CurrentChange_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged("CurrentChange");
OnPropertyChanged(e.PropertyName);
}
private void btnSelectEngineer_Click(object sender, RoutedEventArgs e)
{
byContact newContact = new frmSearchEngineer().ShowSearch();
if (newContact != null)
{
CurrentChange.Engineer = newContact;
PropertyChanged(CurrentChange, new PropertyChangedEventArgs("LeadingSet"));
PropertyChanged(CurrentChange.LeadingSet, new PropertyChangedEventArgs("LeadingSet"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(CurrentChange, new PropertyChangedEventArgs(propertyName));
}
}
}
I've realised the problem may be due to the LeadingSet, returned when the engineer is changed, being a different instance to that in the ObservableCollection.
I'm trying to get the databinding I need to work with a ListBox.
I've parsed some data from a text file to a ObservableCollection<ViewModel> but the data isn't updating in the ListBox.
Here's some information:
The data which is written to from the parser:
class MainData
{
private static ObservableCollection<GroupViewModel> groupModelList = new ObservableCollection<GroupViewModel>();
public static ObservableCollection<GroupViewModel> GroupModelList
{
get { return groupModelList; }
}
}
What GroupViewModel holds (not everything but it's all the same):
class GroupViewModel : INotifyPropertyChanged
{
private GroupModel groupModel;
public event PropertyChangedEventHandler PropertyChanged;
public GroupViewModel()
{
groupModel = new GroupModel();
}
public string Name
{
get { return groupModel.name; }
set
{
if (groupModel.name != value)
{
groupModel.name = value;
InvokePropertyChanged("Name");
}
}
}
...
}
And what GroupModel Holds:
class GroupModel
{
public string name { get; set; }
}
This is how the parser adds new items to the GroupModelView:
if (split[0] == "group")
{
currentGroup = new GroupViewModel();
currentGroup.Name = split[1];
MainData.GroupModelList.Add(currentGroup);
}
I created a ListBox in my WPF application with these XAML options:
<Window x:Class="SoundManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:SoundManager.ViewModels"
xmlns:vm2="clr-namespace:SoundManager.Code"
Title="MainWindow" Height="720" Width="1280">
<Window.Resources>
<vm:MainViewModel x:Key="MainViewModel" />
<vm2:MainData x:Key="MainData" />
</Window.Resources>
<ListBox Grid.Row="2" Height="484" HorizontalAlignment="Left" Margin="12,0,0,0" Name="lbFoundItems" VerticalAlignment="Top" Width="201" ItemsSource="{Binding Source={StaticResource MainData}, Path=GroupModelList/Name}" />
but for some reason the data isn't updating in the UI (new items aren't added visibly in the UI).
I've been just getting started with the MVVM pattern and databinding and I can't figure out what I'm doing wrong.
Thanks in advance!
GroupModelList/Name is not a valid property path here. Setting it like that does not make the ListBox show the Name property of the data items in the GroupModelList collection.
You would instead have to set the ListBox's DisplayMemberPath property:
<ListBox ItemsSource="{Binding Source={StaticResource MainData}, Path=GroupModelList}"
DisplayMemberPath="Name"/>
or set the ItemTemplate property:
<ListBox ItemsSource="{Binding Source={StaticResource MainData}, Path=GroupModelList}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Moreover, the GroupModelList property should not be static:
class MainData
{
private ObservableCollection<GroupViewModel> groupModelList =
new ObservableCollection<GroupViewModel>();
public ObservableCollection<GroupViewModel> GroupModelList
{
get { return groupModelList; }
}
}
Then you might have MainData as a property in your view model, and bind the ListBox like this:
<ListBox ItemsSource="{Binding Source={StaticResource MainViewModel},
Path=MainData.GroupModelList}" .../>
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>