I am trying to create a TreeView nested structure with the use of self referencing table fields. Here is a simple example:
Category 1
Product 1
Toy 1
Toy 2
Product 2
Toy 3
Toy 4
more categories..
The database table has a single table called "Category". The ParentCategoryId points to the Category which is the parent. So, for the Category 1 the ParentCategoryId is null since it is parent. For Product 1 the ParentCategoryId is that of the Category 1 id and for Toy 1 the ParentCategoryId is that for the Product 1 id.
I am using the following code but it does not generate the TreeView (ASP.NET) successfully.
public void BuildTree(List<Category> categories, TreeNode treeNode)
{
if (treeNode == null) return;
TreeNode tnAdd = null;
var categoryId = Guid.NewGuid();
foreach (var category in categories)
{
if (category.IsBaseCategory)
{
tnAdd = new TreeNode();
tnAdd.Text = category.Description;
BuildTree((from c in categories
where c.ParentCategoryId == category.CategoryId
select c).ToList<Category>(), tnAdd);
}
else
{
tnAdd = new TreeNode();
tnAdd.Text = category.Description;
BuildTree((from c in categories
where c.ParentCategoryId == category.CategoryId
select c).ToList<Category>(), tnAdd);
}
if (tnAdd != null)
treeNode.ChildNodes.Add(tnAdd);
}
}
Does this require recursion!
and here is the result I get:
80W
40W
40W
Light Bulbs
Flourecent
Incedecent
60W
80W
60W
Flourecent
40W
80W
60W
Incedecent
80W
40W
60W
What isn't successful?
If its because you see nothing ... I don't see where you're ever adding the root node to the actual tree control. tnAdd needs to be added to the tree control somewhere.
If it's because your not getting everything you expect: Unless you already have recursion going on somewhere and don't realize it, I can't see how the above code is ever going to get to the toy level. You say "base", then "child" in the above code which covers two levels. You have three levels in your sample data, so at some point you need to account for adding the toys. You can write it recursively if you need to have n levels. If you only have three levels, you can just repeat yourself.
----- UPDATES FOR OP UPDATES
Looking at your code, what you have is this:
for each category {
if it is base
add its children
else if it is not base
add its children
add it to the tree
}
This means every item is hit in the first foreach and added to the tree, rather than per level.
what you want is
for each category{
if it is base
add base's children
for each child [
add child's children
add child to the tree
]
add base the tree
}
Something closer to this (I don't have time to test right now, sorry) should come close to working
public BuildTreeTop(List<Category> categories, TreeNode treeNode)
{
BuildTree((from c in categories
where c.IsBaseCategory == true
select c).ToList<Category>(), categories, tnAdd);
}
public void BuildTree(List<Category> currentLevel, List<Category> allCategories, TreeNode treeNode)
{
if (treeNode == null) return;
TreeNode tnAdd = null;
var categoryId = Guid.NewGuid();
foreach (var category in currentLevel)
{
tnAdd = new TreeNode();
tnAdd.Text = category.Description;
BuildTree((from c in allCategories
where c.ParentCategoryId == category.CategoryId
select c).ToList<Category>(), allCategories, tnAdd);
if (tnAdd != null)
treeNode.ChildNodes.Add(tnAdd);
}
}
Related
I just started a new Project _NewEnglandPatriots.
EDTs:
FirstName (extends Name)
SecondName(extends Name)
LastName (extends Name)
Position (String)
PlayerBirthday (Date)
JerseyNumber (Integer)
Tables:
SycTeamRoster (I've dragged all my EDTs to the "Fields" of the table)
Forms:
TeamRoster (I've dragged all the fields into my SimpleList design)
I have inserted the following player data to the form without a problem:
Thomas Edward
Patrick
Brady
12
Quarterback
03.08.1977
Next I wrote a Job insertTeamMembers, within which I insert the member with the following code:
static void insertTeamMembers(Args _args)
{
SycTeamRoster newEnglandTable;
container teammembers;
container conTake;
int i;
;
teammembers = [["Khashayar" ,"Goudarzi", 1, "Quarterback", 28,02,1990]];
ttsBegin;
for(i=1; i<=conLen(teammembers); i++)
{
conTake= conPeek(teammembers,i);
newEnglandTable.clear();
newEnglandTable.SycVorname = conPeek(teammembers,1);
newEnglandTable.SycNachname = conPeek(teammembers,2);
newEnglandTable.SycJerseyNumber = conPeek(teammembers,3);
newEnglandTable.SycPosition = conPeek(teammembers,4);
newEnglandTable.SycPlayerBirthday = conPeek(teammembers,5);
newEnglandTable.insert();
}
ttsCommit;
}
The problem is that I get the following data to the Form and Table:
FirstName: Khashayar
SecondName: empty, but because I left it that way
LastName: empty
JerseyNumber: 0
FieldPosition: 0
Birthday: empty
What is causing these empty fields in the table?
These lines are using teammembers instead of conTake
newEnglandTable.SycVorname = conPeek(teammembers,1);
Change to
newEnglandTable.SycVorname = conPeek(conTake,1);
And the way you have data entered in your nested container, specifically 28,02,1990 is going to be a problem.
This appears to be a learning exercise, so I don't want to solve the entire thing for you.
I want help in linked list implementation of a tree. A tree node has three child.
using pointers: Parent, Siblings and FirstChild.
I have tried making it but couldn't get it to work. I need help in inserting new nodes
void InsertFirstChild(Node newNode)
{
newNode.m_Parent = this;
newNode.m_NextSibling = m_FirstChild;
if (m_FirstChild != null)
m_FirstChild.m_PrevSibling = newNode;
else
m_LastChild = newNode;
m_FirstChild = newNode;
}
I am getting a stack overflow with the following code. I know what the problem is, that it executes all "GetAllPages" in the
Children = new LazyList<Page>(from p in GetAllPages(language)
where p.ParentPage == s.Id
select p)
before it adds the p.ParentPage == s.Id
private IQueryable<Page> GetAllPages(string language)
{
return from s in context.Pages
where (from c in GetAllContent()
where c.PageId == s.Id &&
c.Language.ToLower() == language.ToLower()
select c).Any()
let contents = (from c in GetAllContent()
where c.PageId == s.Id
select c)
select new Page()
{
Id = s.Id,
SiteId = s.SiteId,
Type = s.Type,
Template = s.Template,
ParentPage = s.ParentPage,
Visible = s.Visible,
Order = s.Order,
Contents = contents.ToList(),
Children = new LazyList<Page>(from p in GetAllPages(language)
where p.ParentPage == s.Id
select p)
};
}
How can i do this, correctly?
UPDATE:
The reason behind the code is that, i have a tree structured menu, where one menu item can have 0 to many child items.
The language part can be skipped, but my site support multiple languages, and with the language parameters do i only want menu items there have a content of the given language.
From the moment that you call this GetAllPages(language), and then call it again with out change the language you get 100% stack overflow.
You need to get something that is different, not the same ! and your only parameter is the language and this is not change.
private IQueryable<Page> GetAllPages(string language)
{
....
Children = new LazyList<Page>(from p in GetAllPages(language) // <-- here you
// call him self again with the same parametre.
// Your function is going to call him self asking the same think
// This is bring the stack overflow
// When you make call to the same function you need some how
// to get different results with some different parameter.
Are anyone aware of any method to achieve indentation in the ASPXGridView (we are running the 10.x version currently available)
What we got
What we'd like to achieve
Some information about the code-behind.
The grid is populated by an ObjectDataSource and the indentation is stored in a property alongside with the other data. In example the BMI row will have 0 indentation while the GENDER will have 1, and MAN will have 2. Etc...
The indentation is calculated runtime since relations might change.
public void GetItemsRecursive(int? parentId, int level)
{
List<qstFeedbackLine> q;
if (parentId == 0)
q = _db.qstFeedbackLines.Where(x => x.ParentId == null).ToList();
else
q = _db.qstFeedbackLines.Where(x => x.ParentId == parentId).ToList();
foreach (var item in q)
{
// Store the indent
item.Indent = level;
// Add item to List
_items.Add(item);
level++;
// ...and get the children of the current id
GetItemsRecursive(item.FeedBackLineId, level);
}
}
Any advice out there?
Thanks!
Ended up using the ASPxTreeList component instead!
http://demos.devexpress.com/ASPxTreeListDemos/
I have a LINQ query like this:
from i in _db.Items.OfType<Medium>()
from m in i.Modules
from p in m.Pages
where i != null && i.Type == 1 && i.Published == true && p.PageId == 2
select p
I use the query like this because I have strongly typed view (ASP.NET MVC).
I need to have items sorted by the i.Sort property. orderby i.Sort and i.OrderBy(it => it.Sort) doesn't work. How can I fix this?
When sorting with Linq you usually give OrderBy a property, and eventually an IComparer, not a sorting function. For example:
class Person {
public int Age {get; set;}
}
public static void Main() {
var ps = new List<Person>();
ps.Add(new Person{Age = 1});
ps.Add(new Person{Age = 5});
ps.Add(new Person{Age = 3});
var sorted = ps.OrderBy(p => p.Age);
foreach(p in sorted) {
Console.WriteLine(p.Age);
}
}
Here Linq will know how to correctly sort integers.
Without giving more context (such as what exactly is i.Sort, what is its purpose, what do you want to do with it), it would be difficult to be more specific to your problem.
However, I'm pretty sure you are misunderstanding OrderBy: you should give it a lambda expression that identifies a property of the objects contained in your sequence, and then Linq will sort your sequence according to the usual order of the type of that property (or according to another order you define for that type, by using IComparer).
Let's say your Pages include page-numbers among their properties. Let's pretend this property is called "pagenumber". You would then add the following 'orderby' line between the 'where' and 'select' lines.
// (snip...)
where i != null && i.Type == 1 && i.Published == true && p.PageId == 2
orderby p.pagenumber
select p
Or maybe you don't have page numbers, but only page titles. You would do nearly the same thing:
where i != null && i.Type == 1 && i.Published == true && p.PageId == 2
orderby p.title
select p
Just from reading your code, I can't tell what criteria should be used for sorting. You need some kind of ordered element, an id number, a page number, or some text can be alphabetized.
from i in _db.Items.OfType<Medium>().OrderBy(x => x.Sort)
...