TreeView and Entity Framework binding - c#

I'm new to WPF and EF; I've looked but I wasn't able to find appropriate help.
This is what I have:
Entity Framework (ReportDefinition.ParentID and ReportDefinition.SectionID are Section.idSections), ReportDefinition example and Section example.
This is what I would like to present:
TreeView.
.
I'm trying to achieve this programmatically. I would much appreciate any help.

You need a collection of top-level ReportDefinition objects:
TopLevelReportDefinitions = ReportDefinitions.Where(rd => rd.ParentID == 0)
You need to bind this collection to the ItemsSource of the TreeView.
In EF, you also need to create a parent-child relation on ReportDefinition linking the children to the parent using ParentID. For convenience you can name the reverse collection Children. The collection of ReportDefinition objects directly below another ReportDefinition is then the collection:
ReportDefinition.Children
You then have to create HierarchicalTemplate in the TreeView:
<TreeView ItemsSource="{Binding TopLevelReportDefinitions}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

Related

WPF TreeView data binding to custom objects

I am having trouble understanding how to Bind Data to a WPF TreeView when custom objects are used. I have researched and watched tutorials but I am still stuck.
BACKGROUND: consider three classes (I have simplified my problem to this). They represent a database which has a Table, each table can have Fields. There are a list of Tables.
1) TableList Class
With Property
List<Table Objects>
2) Table Class:
Property Name
With a TableFields Property
SortedDictionary <Name, Field Object>
3) Field Class:
With a Name Property
An example of my current attempt to bind a field (lowest level) to Table.TableFields.Key
<DataTemplate x:Key="fieldTemplate">
<TextBlock Text="{Binding Path=Table.TableFields.Key}"/>
</DataTemplate>
DESIRED OUTPUT - a hierarchical view of the table list, containing tables and their fields.
Table 1
Field 1
Field 2
Field 3
Table 2
Field 1
Field 2
Field 3
Table N
Field N
I am after guidance so I can better understand how to bind this data, an example of my issue is the data binding has to look at a Table Objects TableFields property which is a SortedDictionary, in which I want to get the Key which will be a Field Name.
I am confused with how to bind custom objects and access the information like this.
This will display your TreeView
<TreeView ItemsSource="{Binding TableList}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource = "{Binding Path=TableFields}">
<TextBlock Text="{Binding Path=Name}"/>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Key}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

Treeview "Items collection must be empty before using ItemsSource."

If I use the following code without <DataTemplate> it is working and I can see only the SoftwareVersion, when I add <DataTemple> throws an exception. Any idea why?
ObservableCollection<Note> AllNotes
<TreeView Name="tree" ItemsSource="{Binding Path=AllNotes}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type m:Note}" ItemsSource="{Binding Path=ListIssuesType}">
<TextBlock Text="{Binding Path=SoftwareVersion}" Margin="2" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<DataTemplate DataType="{x:Type m:IssueType}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=IssueTypeName}" />
</StackPanel>
</DataTemplate>
</TreeView>
It is not clear at all why you are adding a DataTemplate to your control. But it is clear why you are getting the exception: you have added the DataTemplate object as a direct child of the TreeView, which makes it an item in the Items collection. It's "template" nature becomes completely irrelevant; you are telling the control to just include that object as an element in the view.
And of course, now that the Items collection is non-empty, you are not allowed to send the ItemsSource property.
So the fix for the exception is "don't do that". I.e. stop trying to make the DataTemplate element an item in the tree view's list of items.
Beyond that, there's not enough context in your question to say how you should be using the DataTemplate object. Presumably you intend it to be used as part of the template for an actual data item in the tree view; maybe it needs to be incorporated into the HierarchicalDataTemplate somehow.
But without more specifics regarding exactly what the code does now and what you want it to do instead, as well as you providing a good Minimal, Complete, and Verifiable example clearly illustrating your scenario, I don't see a good way to address that part of your problem. If you still need help with defining the data template, please post a new question that provides the necessary details.

Create custom tree view with a dynamic context menu C# WPF

I want to create a dynamic tree view from a list in C# WPF. So I will get all the queues (queue1, ...) and topics (topic1, ...) from a list. Furthermore I need a specific context menu for the different hierarchical points. I want to create a tree view like this:
queues
queue1
queue2
topics
topic1
topic2
There should be a specific context menu for the main point queues and a specific for the main point topics. Additional I need a specific for the subitems queues1 and the topic1. I tried a few things but without success. Has anybody a small example which shows who to solve this problem?
Best Regards
Creating a tree is not an issue. It involves bit of work, but straight forward. You have to create a hierarchical data template from your list and get the tree populated. Following link has all the info.
Creating a wpf tree
OR if you don't want to use sdk
page resource:
tree in xaml:
<Grid TextElement.FontSize="10" DataContext="{StaticResource MyHierarchicalViewSource}" >
<GroupBox x:Name="gbTree">
<TreeView Name="HierarchyTreeview" HorizontalAlignment="Left" AllowDrop="True"
BorderThickness="0" VerticalAlignment="Top" Height="Auto"
ItemsSource="{Binding}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Itemchildren, Mode=TwoWay}">
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock x:Name="text" Text="{Binding Item.ItemLabel}" >
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</GroupBox>
</Grid>
code behing:
Me._HierarchyViewSource = CType(Me.Resources("MyHierarchicalViewSource"), System.Windows.Data.CollectionViewSource)
Me._HierarchyViewSource.Source = your hierarchical data collection
assuming your hierarchy class structure:
Item has
ItemChildren collection
However,I have the same issue in creating a specific context menu. I have posted my own question and haven't found a solution yet. I tried to do it with data triggers with no luck. The only way I know is creating a context menu for the whole tree and make it visible or invisible depending on item type.
If I find a workaround, I will post.
I used the following code for add to TreeView dynamically.
CategorieList - Collection of categories which has id, name, bool value as IsSubCategory and Id of parent category.
private void AddToTree()
{
List<Category> topCategory = CategorieList.Where(c => c.IsSubCategory == false).ToList();
foreach(Category c in topCategory)
{
CategoryTree.Items.Add(CreateTreeViewItem(c));
}
}
private TreeViewItem CreateTreeViewItem(Category category)
{
TreeViewItem tItem = new TreeViewItem();
tItem.Header = category.Name;
List<Category> sub = CategorieList.Where(c => category.Id == c.ParentCategory).ToList();
if (null != sub && sub.Count() != 0)
{
foreach (Category c in sub)
{
TreeViewItem item = CreateTreeViewItem(c);
tItem.Items.Add(item);
}
}
return tItem;
}
XAML code is below
<TreeView x:Name="CategoryTree"> </TreeView>

C# TreeView and binding to a database

I'm querying a database via a stored procedure and getting data back. which I'm populating into an object as such:
private GetMiscVars _batchVariablesData;
public GetMiscVars BatchVariablesData
{
get { return _batchVariablesData; }
set
{
if (_batchVariablesData == value) return;
_batchVariablesData = value;
OnPropertyChanged("BatchVariablesData");
}
}
In my XAML I have this:
<TreeView>
<TreeViewItem Header="Batch Data" ItemsSource="{Binding BatchVariablesData}">
<TreeViewItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding VarDesc}" />
</DataTemplate>
</TreeViewItem.HeaderTemplate>
</TreeViewItem>
</TreeView>
What I am seeing when my code runs is my parent node is blank instead of saying "Batch Data" like I hoped and my child nodes return the name of the ObservableCollection used in calling the database, in this DgTabData.
So, where am I screwing things up?
Thanks
To clarify a little bit more, I have a stored procedure that returns data that looks like this:
VarId EventId VarDesc
11 2489 WP1.WC01 Quantity
1196 2489 WP1.WC01 Brew Number
1197 2489 WP1.WC01 Operator Name
1216 2489 WP1.WC01 Integer Test
1217 2489 WP1.WC01 Logical Test
1218 2489 WP1.WC01 Float-4 Test
1219 2489 WP1.WC01 Float-3 Test
I want to take the VarDesc field and place it in a TreeView under a heading of Batch Data. Once I can figure this out I want to be able to grab the VarId and EventId values from the item selected in the TreeView as I will use those to populate a datagrid.
Firstly, a TreeView displays hierarchical data. That means that your data must have a public collection property to use for the child nodes. Next, to display hierarchical data, you need to declare a HierarchicalDataTemplate, rather than trying to define the controls as you were. Try this XAML instead:
<TreeView ItemsSource="{Binding CollectionOfParents}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type YourPrefix.YourClassName}"
ItemsSource="{Binding CollectionOfChildrenPropertyInParent}">
<TextBlock Text="{Binding PropertyInParent}" /><!-- Parent DataTemplate -->
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate> <!-- Child DataTemplate -->
<TextBlock Text="{Binding PropertyInChild}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
UPDATE >>>
As I said, a TreeView displays hierarchical data. That means that your data must have a public collection property to use for the child nodes. So create a class, let's say named Data, with a property to hold the Batch Data text, let's say named Name, and an ObservableCollection<string> property, let's say named Items to hold the VarDesc column values.
Then you need to populate the collection with the items returned from the stored procedure in any way you see fit. Finally, create an ObservableCollection<Data> property, let's say named DataItems in the code behind or view model and add your Data class, complete with collection items. Then you could bind to the TreeView like this:
<TreeView ItemsSource="{Binding DataItems}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type YourXamlNamespacePrefix.Data}"
ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Name}" /> <!-- Parent DataTemplate -->
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate> <!-- Child DataTemplate -->
<TextBlock Text="{Binding}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>

WPF Databinding Treeview to List does not update

I have a List bound to a TreeView like:
XAML:
<TreeView Name="browserTree"
BorderBrush="DarkSlateGray"
BorderThickness="1"
Grid.Row="2"
Margin="0,3,0,0"
ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}">
<TreeView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
C#:
browserTree.DataContext = treeList;
I update the list via:
void QueryChange(string s)
{
rCM.SetCommand(s);
treeList.Clear();
SqlDataReader sr = rCM.ExecuteReader(System.Data.CommandBehavior.Default);
while (sr.Read())
{
treeList.Add((string)sr["tree_hdr"]);
}
sr.Close();
}
The List<string> is just a placeholder at the moment for a more meaningful data class I have yet to implement. But right now I need to know why the TreeView is not updating to reflect the changes made to the list.
Try making the treelist an ObservableCollection.
Please check the type of your treeList which you set as DataContext. It has to be an ObservableCollection to reflect your collection changes in the UI
Or else for quick workaround, just set the DataContext again after you filled the List.

Categories

Resources