Binding to an XML list of attributes
-
I have an XML file structured this way:
<Emulators>
<System>
<Name>Name1</Name>
<Kind name="lexplode"/>
<Kind name="sexplode"/>
<Kind name="dropbomb"/>
</System>
</Emulators>If I want to read, in XAML, from <Name> I know that I have to do:
<TextBox Text="{Binding XPath=Name, UpdateSourceTrigger=PropertyChanged}"/>
But what if I want to read all the values under <Kind>> ? And which control could receive them, a textbox, a listbox, ..? Thanks a lot!!
-
I have an XML file structured this way:
<Emulators>
<System>
<Name>Name1</Name>
<Kind name="lexplode"/>
<Kind name="sexplode"/>
<Kind name="dropbomb"/>
</System>
</Emulators>If I want to read, in XAML, from <Name> I know that I have to do:
<TextBox Text="{Binding XPath=Name, UpdateSourceTrigger=PropertyChanged}"/>
But what if I want to read all the values under <Kind>> ? And which control could receive them, a textbox, a listbox, ..? Thanks a lot!!
In order to get the attribute, you have to use a slightly different type of syntax. Rather than using
XPath=name
, you have to useXPath=@name
. Now, that will only get you the value of the currently selectedKind
item, so how do you actually get that item? Well, the answer is to use something like a ListBox to encapsulate the items.<ListBox ItemsSource="{Binding Source={MyEmulatorsList, XPath=//Kind}" ItemTemplate="{StaticResource KindItemsTemplate}" />
Note: In this sample, I'm assuming that you have used an XmlDataProvider called
MyEmulatorsList
to point to this XML. So, where is the actual display of the name item? Well, that's provided by the ItemTemplate, which looks like this:<DataTemplate x:Key="KindItemsTemplate">
<TextBlock Text="{Binding XPath=@name}" />
</DataTemplate>*pre-emptive celebratory nipple tassle jiggle* - Sean Ewington
"Mind bleach! Send me mind bleach!" - Nagy Vilmos
CodeStash - Online Snippet Management | My blog | MoXAML PowerToys | Mole 2010 - debugging made easier
-
In order to get the attribute, you have to use a slightly different type of syntax. Rather than using
XPath=name
, you have to useXPath=@name
. Now, that will only get you the value of the currently selectedKind
item, so how do you actually get that item? Well, the answer is to use something like a ListBox to encapsulate the items.<ListBox ItemsSource="{Binding Source={MyEmulatorsList, XPath=//Kind}" ItemTemplate="{StaticResource KindItemsTemplate}" />
Note: In this sample, I'm assuming that you have used an XmlDataProvider called
MyEmulatorsList
to point to this XML. So, where is the actual display of the name item? Well, that's provided by the ItemTemplate, which looks like this:<DataTemplate x:Key="KindItemsTemplate">
<TextBlock Text="{Binding XPath=@name}" />
</DataTemplate>*pre-emptive celebratory nipple tassle jiggle* - Sean Ewington
"Mind bleach! Send me mind bleach!" - Nagy Vilmos
CodeStash - Online Snippet Management | My blog | MoXAML PowerToys | Mole 2010 - debugging made easier
Thanks for your reply!! I think that I'd better expose the whole code. XML file:
Name1
</Emulators>
VB code:
Class MainWindow
Dim data As XmlDataProvider = New XmlDataProvider()
Private Sub MainWindow_Initialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Initialized
data.Source = New Uri(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\myapplication\Systems.xml")
data.XPath = "Emulators/System"
Grid1.DataContext = data
End Sub
End ClassXAML code:
It doesn't work, I get a
System.Windows.Data Error: 44 : BindingExpression with XPath cannot bind to non-XML object.; XPath='//Kind' BindingExpression:Path=; DataItem='String' (HashCode=2037252866); target element is 'ListBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable') data
-
Thanks for your reply!! I think that I'd better expose the whole code. XML file:
Name1
</Emulators>
VB code:
Class MainWindow
Dim data As XmlDataProvider = New XmlDataProvider()
Private Sub MainWindow_Initialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Initialized
data.Source = New Uri(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\myapplication\Systems.xml")
data.XPath = "Emulators/System"
Grid1.DataContext = data
End Sub
End ClassXAML code:
It doesn't work, I get a
System.Windows.Data Error: 44 : BindingExpression with XPath cannot bind to non-XML object.; XPath='//Kind' BindingExpression:Path=; DataItem='String' (HashCode=2037252866); target element is 'ListBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable') data
You are trying to bind to Emulators in your XPath, but your XML says Base.
*pre-emptive celebratory nipple tassle jiggle* - Sean Ewington
"Mind bleach! Send me mind bleach!" - Nagy Vilmos
CodeStash - Online Snippet Management | My blog | MoXAML PowerToys | Mole 2010 - debugging made easier
-
You are trying to bind to Emulators in your XPath, but your XML says Base.
*pre-emptive celebratory nipple tassle jiggle* - Sean Ewington
"Mind bleach! Send me mind bleach!" - Nagy Vilmos
CodeStash - Online Snippet Management | My blog | MoXAML PowerToys | Mole 2010 - debugging made easier
-
Thanks for your reply!! I think that I'd better expose the whole code. XML file:
Name1
</Emulators>
VB code:
Class MainWindow
Dim data As XmlDataProvider = New XmlDataProvider()
Private Sub MainWindow_Initialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Initialized
data.Source = New Uri(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\myapplication\Systems.xml")
data.XPath = "Emulators/System"
Grid1.DataContext = data
End Sub
End ClassXAML code:
It doesn't work, I get a
System.Windows.Data Error: 44 : BindingExpression with XPath cannot bind to non-XML object.; XPath='//Kind' BindingExpression:Path=; DataItem='String' (HashCode=2037252866); target element is 'ListBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable') data
-
I think I see what the problem is. In the ListBox XAML, you don't need the Source=data (that's incorrect syntax, and besides, you already set the DataContext from the code-behind, so it's not needed. Take that part out, and it should work:
Thank you very much!! For the first time I can see those data displayed!! ;-) Just one think... of importance: ALL the "Kind" attributes are displayed. I've tried a "IsSynchronizedWithCurrentItem="True"" but it doesn't change anything. Any idea on how to fix it, please? The datatemplate for the combobox that displays the system's "Name":
The datatemplate for the ListBox that display the "Kind" name attributes (related to the selected "System"!!):
The WPF controls:
-
Thanks for your reply!! I think that I'd better expose the whole code. XML file:
Name1
</Emulators>
VB code:
Class MainWindow
Dim data As XmlDataProvider = New XmlDataProvider()
Private Sub MainWindow_Initialized(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Initialized
data.Source = New Uri(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\myapplication\Systems.xml")
data.XPath = "Emulators/System"
Grid1.DataContext = data
End Sub
End ClassXAML code:
It doesn't work, I get a
System.Windows.Data Error: 44 : BindingExpression with XPath cannot bind to non-XML object.; XPath='//Kind' BindingExpression:Path=; DataItem='String' (HashCode=2037252866); target element is 'ListBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable') data
-
You can select an item by using the XPath expression. Instead of XPath=//Kind, use XPath=//Kind[0], or XPath=//Kind[1], etc.
dbaseman, Thanks again for taking time to help me! If you consider my XML file
Name1 Name2
Using "XPath=//Kind[1]" will return: "a1, b1" What I would like is "a1, a2, a3" being returned!! How should I please proceed to achieve this (returning all "Kind" attributes of the currently selected "System"? Thanks very much,
-
dbaseman, Thanks again for taking time to help me! If you consider my XML file
Name1 Name2
Using "XPath=//Kind[1]" will return: "a1, b1" What I would like is "a1, a2, a3" being returned!! How should I please proceed to achieve this (returning all "Kind" attributes of the currently selected "System"? Thanks very much,