| 

.NET C# Java Javascript Exception

3
Hallo zusammen

Ich befülle ein TreeView mit XmlNodes. Nach dem der User einen neuen Knoten angefügt Hat, möchte ich diesen per Code selektieren. Nach einiger suchen im Internet bin ich auf folgendes
Beispiel gestossen:

public static void SetXmlItemSelected(ref TreeView container, XmlNode node)
{

if (container.HasItems)
{
//cast to xml-nodes
var xmlNodeList = container.Items.Cast<XmlNode>(); ;

//node at root level? -> select it
if (xmlNodeList.Contains(node))
{
(container.ItemContainerGenerator.ContainerFromItem(node) as TreeViewItem).IsSelected = true;
}
else
{
//get rootnode
XmlNode rootNode = GetRootNode(node, xmlNodeList);

//get a list of parent nodes
List<XmlNode> parentNodes = new List<XmlNode>();
GetAllParentNodes(rootNode, node, ref parentNodes);
parentNodes.Reverse();

//finaly, select the node
SelectNode(parentNodes, node, ref container, null);
}
}

}

private static XmlNode GetRootNode(XmlNode node, IEnumerable<XmlNode> xmlNodeList)
{
if (!xmlNodeList.Contains(node) && node.ParentNode != null)
{
return GetRootNode(node.ParentNode, xmlNodeList);
}
else if (xmlNodeList.Contains(node)) return node;
else return null;
}

private static void GetAllParentNodes(XmlNode rootNode, XmlNode actualNode, ref List<XmlNode> parentNodes)
{
if (actualNode.ParentNode != null && !actualNode.Equals(rootNode))
{
parentNodes.Add(actualNode.ParentNode);
GetAllParentNodes(rootNode, actualNode.ParentNode, ref parentNodes);
}
}

private static void SelectNode(List<XmlNode> parentNodes, XmlNode node, ref TreeView container, [Optional, DefaultParameterValue(null)] TreeViewItem item)
{
if (parentNodes.Count > 0)
{
TreeViewItem tvItem;
if (item != null)
tvItem = item.ItemContainerGenerator.ContainerFromItem(parentNodes.First()) as TreeViewItem;
else
tvItem = container.ItemContainerGenerator.ContainerFromItem(parentNodes.First()) as TreeViewItem;
parentNodes.RemoveAt(0);
SelectNode(parentNodes, node, ref container, tvItem);
}
else if (item != null)
{
(item.ItemContainerGenerator.ContainerFromItem(node) as TreeViewItem).IsSelected = true;
}
}


Jedoch bei der 3. Codezeilen der aufrufenden Funktion:
if (xmlNodeList.Contains(node))
bekomme ich dies Fehlermeldung:

Das Objekt des Typs "System.Windows.Controls.TreeViewItem" kann nicht in Typ "Syst
em.Xml.XmlNode" umgewandelt werden.

Meine Annahme, das die Methode TreeView.Items.Cast<XmlNode> mir eine enumerable Liste mit den XmlNodes zurückgibt, ist wohl irrig.
Auch Boxing hilft mir nicht weiter, weil wohl grundsätzlich eine XmlNode nicht in den Typ TreeViewItem konvertiert werden kann.

Hat jemand eine Idee wie der oben gezeigte Code verändert werden kann oder ein Link der eine gleichwertige funktionierende Funktion enthält?

Feundliche Grüsse

Alex
qa//
03.01.2012
Alex Feuz 85 1 4
Vielleicht postest Du mal den Link auf die Quelle für Dein Code-Beispiel, und zum Vergleich den Code, der Deinen TreeView befüllt.
Matthias Hlawatsch 03.01.2012
2 Antworten
1
Hallo Alex,

ich hab zwar aus Deinem Code nicht ganz verstanden, wie Dein Treeview letztlich befüllt wird, aber folgendes kommt mir sehr spanisch vor:

<TreeView Name="trvTreeViewMain" SelectedItemChanged="trvTreeViewMain_SelectedItemChanged">
<TreeViewItem ItemsSource="{Binding Source={StaticResource RootData}, XPath=*}" Header="Rezeptgruppen" IsExpanded="True" ContextMenu="{StaticResource GroupContextMenu}"/>
</TreeView>


Damit definierst Du einen TreeView mit einem Item, und die Datenquelle für dieses eine Item ist dann das XML-Dokument. Keine Ahnung, warum Du das so machst, aber es hat zur Folge, dass die Items des TreeViews selbst keine XmlNodes sind, sondern nur die Items des ersten TreeViewItems in Deinem Tree. Du müßtest also entweder den XAML-Code aufräumen und die ItemsSource beim TreeView selbst anbringen, oder (falls diese besondere Struktur irgendeinen tieferen Sinn hat) Du baust den Code so um:

// als container muss dann das erste TreeViewItem aus dem TreeView übergeben werden
public static void SetXmlItemSelected(ref TreeViewItem container, XmlNode node)
{
if (container.HasItems)
{
//cast to xml-nodes
var xmlNodeList = container.Items.Cast<XmlNode>();
...
04.01.2012
Matthias Hlawatsch 13,2k 4 9
0
Guten Moregen Matthias

1. Der Link: http://www.humbug.in/stackoverflow/de/how-to-select-a-databound-treeviewitem--5407650.html

2. Das Projekt ist ziemlich gekürzt, ich hoffe, dass ich alle relevanten Teile erwischt habe.

Der XML-File den ich als Gerüst zum einfügen der XmlElemente benutze.

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE Root [
<!ELEMENT Root ANY>
<!ELEMENT Node ANY>
<!ATTLIST Node Id ID #REQUIRED>
<!ATTLIST Node ParentID CDATA #REQUIRED >
<!ATTLIST Node Header CDATA #REQUIRED>
]>
<Root>

</Root>


Das Window:

<Window x:Class="WpfApplication1.XmlTreeviewDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:jsCtr="clr-namespace:js.WPFbase.Controls;assembly=jsWPFbase"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="XmlTreeviewDemo" Height="434" Width="408">
<Window.Resources>
<XmlDataProvider x:Key="RootData" XPath="/Root"/>

<HierarchicalDataTemplate DataType="Node" ItemsSource="{Binding}">
<TextBlock Text="{Binding XPath=@Header}" />
</HierarchicalDataTemplate>

<ContextMenu x:Key="GroupContextMenu">
<MenuItem Header="Neue Hauptgruppe" Command="New"/
<MenuItem Header="Grupppe anfügen" Command="Open"/>
</ContextMenu>
</Window.Resources>
<Grid>
<TreeView Name="trvTreeViewMain" SelectedItemChanged="trvTreeViewMain_SelectedItemChanged">
<TreeViewItem ItemsSource="{Binding Source={StaticResource RootData}, XPath=*}" Header="Rezeptgruppen" IsExpanded="True" ContextMenu="{StaticResource GroupContextMenu}"/>
</TreeView>

</Grid>

</Window>


Die Klasse GroupItem und XmlDoc zum erzeugen des XmlDocument (dies sind orginal in einer dll ausgelagert), sowie der der BehindCode des Windows.

public class GroupItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

private string _header;
private int _id;
private int _parentID;

public GroupItem(string header, int id, int parentID)
{
Header = header;
Id = id;
ParentID = parentID;
}

public string Header
{
get { return _header; }
set
{
_header = value;
Changed("Header");
}
}

public int Id
{
get { return _id; }
set
{
_id = value;
Changed("Id");
}
}

public int ParentID
{
get { return _parentID; }
set
{
_parentID = value;
Changed("ParentID");
}
}


public override string ToString()
{
return Header;
}

private void Changed(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

public class XmlDoc : XmlDocument
{

public XmlDocument GetDocument { get { return this; } }

private XmlElement _rootElement = null;
private int _treeViewIndex = 0;

public XmlDoc(string path)
{
try
{

this.Load(path);

_rootElement = this.DocumentElement;
}

catch (Exception e) { throw e; }

}

public void AddElement(XmlElement element, int parentID)
{
if (parentID < 1)
{
_rootElement.AppendChild(element);
}
else
{
XmlElement el = this.GetElementById(IdToString(parentID));
el.AppendChild(element);
}
}

public string IdToString(int id)
{
return "_" + id.ToString();
}

public int IdToInt(string id)
{
return int.Parse(id.Substring(1));
}

public int GetTreeViewIndex
{
get
{
_treeViewIndex++;
return _treeViewIndex;
}
}

}

public partial class XmlTreeviewDemo : Window
{

private ObservableCollection<GroupItem> _dataCollection;
private XmlDataProvider _dataProvider = null;
private XmlDoc _document = null;
private int _newID = 15;

public XmlTreeviewDemo()
{
CommandBindings.Add(new CommandBinding(ApplicationCommands.New, AddNewGroup));
CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, AddNewGroup));

_dataProvider = (XmlDataProvider)trvMain.FindResource("RootData");

AddData();
AddDocument();

}

private void AddData()
{

_dataCollection.Add(new GroupItem("Fleisch", 1, -1));
_dataCollection.Add(new GroupItem("Rind", 2, 1));
_dataCollection.Add(new GroupItem("Kalb", 3, 1));
_dataCollection.Add(new GroupItem("Schwein", 4, 1));
_dataCollection.Add(new GroupItem("Geflügel", 5, 1));
_dataCollection.Add(new GroupItem("Huhn", 6, 5));
_dataCollection.Add(new GroupItem("Beilagen", 7, -1));
_dataCollection.Add(new GroupItem("Kartoffel", 8, 7));
_dataCollection.Add(new GroupItem("Teigwaren", 9, 7));
_dataCollection.Add(new GroupItem("Teigspeisen", 10, 7));
_dataCollection.Add(new GroupItem("Niocci", 11, 10));
_dataCollection.Add(new GroupItem("Brust", 12, 6));
_dataCollection.Add(new GroupItem("Schnitzel", 13, 12));
_dataCollection.Add(new GroupItem("Geschnetzeltes", 14, 12));

}


private void AddDocument()
{

_document = new XmlDoc("MyPtah");

foreach (cit.GroupItem item in _dataCollection)
{
if (item.ParentID == -1)
{
_document.AddElement(CreateNewElement(item), -1);
}
else
{
_document.AddElement(CreateNewElement(item), item.ParentID);
}
}

_dataProvider.Document = _document.GetDocument;

}

private XmlElement CreateNewElement(GroupItem item)
{

XmlAttribute atId = _document.CreateAttribute("Id");
atId.Value = _document.IdToString(item.Id);
XmlAttribute atPId = _document.CreateAttribute("ParentID");
atPId.Value = item.ParentID.ToString();
XmlAttribute atHeader = _document.CreateAttribute("Header");
atHeader.Value = item.Header;

XmlElement el = _document.CreateElement("Node");
el.Attributes.Append(atId);
el.Attributes.Append(atPId);
el.Attributes.Append(atHeader);

return el;

}

private void AddNewGroup()
{
GroupItem item = new GroupItem("Irgendwas", _newID, -1);
_newID++;
_document.AddElement(CreateNewElement(item),-1);

SetElementSelected(item);

}

private void AddGroup()
{

int parentID = _document.IdToInt(GetSelectedItem().Attributes["Id"].Value);
GroupItem item = new GroupItem("Irgendwas", _newID, parentID);
_newID++;

_document.AddElement(CreateNewElement(item), -parentID);
//Da hier im TreeView das Element nicht angezeigt wird, den TreeView neu laden
AddDocument();

SetElementSelected(item);
}


private XmlNode GetSelectedItem()
{
try
{
return (XmlNode)trvMain.SelectedItem;
}
catch { return null; }
}


private void SetElementSelected(GroupItem item)
{
XmlNode nd = _document.GetElementById(_document.IdToString(item.Id));
//Hier kommt der Aufruf zu der Function, siehe Link

}


}


Ich hoffe, dass Du mit diesen Angaben klar kommst.

Gruss Alex
04.01.2012
Alex Feuz 85 1 4
Bitte verschiebe diesen Post in Deine Frage (per Edit-Funktion). Antworten sind hier für Antworten auf die ursprüngliche Frage gedacht, nicht für Antworten auf Rückfragen in Kommentaren.

Im übrigen scheint der Code nicht ganz konsistent zu sein: im XAML heißt es trvTreeViewMain, im Code-Behind aber trvMain.
Matthias Hlawatsch 04.01.2012

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH