Reputation: 2525
I have two classes defined which look like this:
public class Task {
public string TaskName { get; set; }
public string Description { get; set; }
public string Priority { get; set; }
public List<Job> listofjobs = new List<Job>();
}
public class Job
{
public string ID { get; set; }
public string Name { get; set; }
}
After generating the data I have several Task objects in a List:
public static List<Task> tasklist = new List<Task>();
Each of those tasks has several jobs in it. This list gets databound to a listbox. like this:
Task newTask = new Task();
Job newJob = new Job();
Job newJob2 = new Job();
newTask.Description = "Task 1";
newJob.job_name = "Job 1";
newJob.job_name = "Job 2";
newTask.listofjobs.Add(newJob);
newTask.listofjobs.Add(newJob2);
tasklist.Add(newTask);
joblist.ItemsSource = tasklist;
The XAML looks like this:
<ListBox Name="joblist" HorizontalContentAlignment="Stretch" >
<ListBox.ItemTemplate>
<DataTemplate>
<Expander Name="jobgroup" Header="{Binding Path=Description}" HorizontalAlignment="Stretch" Padding="5" FontSize="16" VerticalAlignment="Top">
<Expander.ContentTemplate>
<DataTemplate>
<Border>
<WrapPanel>
<Label Content="{Binding Path=ID, RelativeSource={RelativeSource AncestorType=local:Job}}"></Label>
</WrapPanel>
</Border>
</DataTemplate>
</Expander.ContentTemplate>
</Expander>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Generating the expanders by Databinding works flawlessly. Generating the the content of the expanders on the other hand just does now want to work.
I want to achieve that the jobs within the Task objects get generated by databinding to the WrapPanels within the designated expander Content.
The result should be that i have several expanders (the Task objects) with several wrappanels in the content (the Job objects of the Parent task).
Does anyone know what I am doing wrong here / how to achieve this?
EDIT:
With the anwers provided I tried:
<Expander Name="jobgroup" Header="{Binding Path=Description}" HorizontalAlignment="Stretch" Padding="5" FontSize="16" VerticalAlignment="Top">
<ListView ItemsSource="{Binding Path=listofjobs}" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Label Content="{Binding Path=Name}"></Label>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Expander>
and also:
<DataTemplate>
<Expander Name="jobgroup" Header="{Binding Path=Description}" HorizontalAlignment="Stretch" Padding="5" FontSize="16" VerticalAlignment="Top">
<ListView ItemsSource="{Binding Path=listofjobs}" >
<StackPanel Orientation="Vertical">
<Label Content="{Binding Path=Name}"></Label>
</StackPanel>
</ListView>
</Expander>
</DataTemplate>
But both does not seem to work. What am i missing here?
EDIT2:
There are several binding errors showing up:
System.Windows.Data Error: 40 : BindingExpression path error: 'listofjobs' property not found on 'object' ''Task' (HashCode=49998812)'. BindingExpression:Path=listofjobs; DataItem='Task' (HashCode=49998812); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=listofjobs; DataItem='Task' (HashCode=49998812); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=listofjobs; DataItem='Task' (HashCode=49998812); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=listofjobs; DataItem='Task' (HashCode=49998812); target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Error: 40 : BindingExpression path error: 'Name' property not found on 'object' ''Task' (HashCode=49998812)'. BindingExpression:Path=Name; DataItem='Task' (HashCode=49998812); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')
System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=Name; DataItem='Task' (HashCode=49998812); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')
System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=Name; DataItem='Task' (HashCode=49998812); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Name; DataItem='Task' (HashCode=49998812); target element is 'Label' (Name=''); target property is 'Content' (type 'Object')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'ListViewItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=VerticalContentAlignment; DataItem=null; target element is 'ListViewItem' (Name=''); target property is 'VerticalContentAlignment' (type 'VerticalAlignment')
Upvotes: 1
Views: 1900
Reputation: 5083
Since you are binding Description
successfully your binding must be List<Task> tasklist
.
Imagine your visual tree like that:
- ListBox - Binds List<Task>
- ListBoxItem (Expander) - Binds Task
- ListBoxItem (ExpanderContent)- ListView - Binds Task.Jobs (List<Job>)
- ListView.ItemTemplate - Binds Job
So you can only access properies of Task
.
Your Expanders
ControlTemplate
should be something to show the collection of Job
s:
<Expander.ContentTemplate>
<DataTemplate>
<ListView ItemsSource="{Binding Jobs}" >
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</Expander.ContentTemplate>
OR
You only bind one job like this:
<Label Content="{Binding Path=Jobs[0].ID" />
You don't need any RelativeSource
here.
Make sure every property you bind to has a getter/setter {get; set;} !
public List<Job> ListOfJobs {get; set;} = new List<Job>();
Upvotes: 2
Reputation: 1709
I think it would be easier to Bind your VM entirely in your Listbox, like this:
<ListBox Name="joblist" HorizontalContentAlignment="Stretch" ItemsSource={Binding Path=tasklist}> ... </ListBox>
The expander could stay the same :
<Expander Name="jobgroup" Header="{Binding Path=Description}" HorizontalAlignment="Stretch" Padding="5" FontSize="16" VerticalAlignment="Top">
And for your content define do it like this:
<ListView ItemsSource={Binding Path=listofjobs} >
<StackPanel Orientation="Vertical">
<Label Content="{Binding Path=ID}"></Label>
</StackPanel>
</ListView>
Expose your tasklist as a property, and define it as the DataContext of your page/listbox and i think it should be working correctly.
Upvotes: 0