how to bind xml file in listbox? - wpf

I have an xml file as shown:
<?xml version="1.0" encoding="utf-8"?>
<PhoneBook xmlns="http://tempuri.org/PhoneBook.xsd">
<Person>
<PersonItem name="name1" famil="famil1">
<Numbers>
<NumbersItem number="123456" />
<NumbersItem number="789100" />
</Numbers>
</PersonItem>
</Person>
<Person>
<PersonItem name="name2" famil="famil2">
<Numbers>
<NumbersItem number="654321" />
<NumbersItem number="111213" />
</Numbers>
</PersonItem>
</Person>
</PhoneBook>
I have successfully bound a listbox to this XML using the following:
Imports <xmlns:DaftarTelephone="http://tempuri.org/PhoneBook.xsd">
Dim xmlPhoneBook = XDocument.Load(CurDir() & "\PhoneBook.xml")
Dim q = From el In xmlPhoneBook ...<PhoneBook:PersonItem>
lst.ItemsSource = q 'my listbox
Here's my XAML:
<Page.Resources>
<DataTemplate x:Key="PersonItemTemplate">
<StackPanel>
<TextBlock Text="{Binding Path=Attribute[famil].Value}"/>
<TextBlock Text="{Binding Path=Attribute[name].Value}"/>
<TextBlock Text="{Binding Path=Attribute[number].Value}"/>
</StackPanel>
</DataTemplate>
</Page.Resources>
<Grid x:Name="LayoutRoot" >
<ListBox x:Name="lst" ItemsSource="{Binding}" ItemTemplate="{DynamicResource PersonItemTemplate}" />
</Grid>
family and name is shown correctly. But numbers are not shown!!!

Related

WPF combobox does not show values at runtime

I am a newbie with WPF.
I have a combobox bound to an XML datasource defined in the Window.Resources.
The combobox values are shown in the designer, but it comes out empty at runtime.
Am I missing something here.
<Window x:Class="WpfExample4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<XmlDataProvider x:Key="xmlData">
<x:XData>
<customers>
<customer name="Customer 1">
<order desc="Big Order">
<orderDetail product="Glue" quantity="21" />
<orderDetail product="Fudge" quantity="32" />
</order>
</customer>
<customer name="Customer 2">
<order desc="First Order">
<orderDetail product="Mousetrap" quantity="4" />
</order>
</customer>
</customers>
</x:XData>
</XmlDataProvider>
</Window.Resources>
<Grid DataContext= "{Binding Source={StaticResource xmlData}, XPath=customers/customer}" Margin="4" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<!-- CUSTOMERS -->
<DockPanel Grid.Row="0">
<TextBlock DockPanel.Dock="Top" FontWeight="Bold" Text="Customers" />
<ComboBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding XPath=#name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DockPanel>
</Grid>
</Window>
You should add namespace to root element (msdn).
Note:
The root node of the XML data has an xmlns attribute that sets the XML
namespace to an empty string. This is a requirement for applying XPath
queries to a data island that is inline within the XAML page. In this
inline case, the XAML, and thus the data island, inherits the
System.Windows namespace. Because of this, you need to set the
namespace blank to keep XPath queries from being qualified by the
System.Windows namespace, which would misdirect the queries.
...
<Window.Resources>
<XmlDataProvider x:Key="xmlData">
<x:XData>
<customers xmlns="">
<customer name="Customer 1">
<order desc="Big Order">
<orderDetail product="Glue" quantity="21" />
<orderDetail product="Fudge" quantity="32" />
</order>
</customer>
...

WPF XML DataBinding not working

I have below xml file. I have copied it into my project debug/bin folder & have also attached to my project.
<?xml version="1.0" standalone="yes" ?>
- <NorthwindDataSet xmlns="http://tempuri.org/NorthwindDataSet.xsd">
- <Customers>
<CustomerID>ALFKI</CustomerID>
<CompanyName>Alfreds Futterkiste</CompanyName>
<ContactName>Maria Anders</ContactName>
<ContactTitle>Sales Representative</ContactTitle>
<Address>Obere Str. 57</Address>
<City>Berlin</City>
<PostalCode>12209</PostalCode>
<Country>Germany</Country>
<Phone>030-0074321</Phone>
<Fax>030-0076545</Fax>
</Customers>
- <Customers>
<CustomerID>ANATR</CustomerID>
<CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
<ContactName>Ana Trujillo</ContactName>
<ContactTitle>Owner</ContactTitle>
<Address>Avda. de la Constitución 2222</Address>
<City>México D.F.</City>
<PostalCode>05021</PostalCode>
<Country>Mexico</Country>
<Phone>(5) 555-4729</Phone>
<Fax>(5) 555-3745</Fax>
</Customers>
</NorthwindDataSet>
I want to bind properties like CustomerName, City in my WPF application. I tried to bind it in XAML as below, but not getting success. Need suggetsion, what I am doing wrong.
<Window.Resources>
<XmlDataProvider x:Key="NorthData" Source="Northwind.xml" XPath="/Customers"/>
</Window.Resources>
<Grid>
<Label Content="{Binding XPath=Address,FallbackValue=BindingFailed,Source={StaticResource NorthData}}" Height="28" HorizontalAlignment="Left" Margin="118,94,0,0" Name="label1" VerticalAlignment="Top" Width="127" />
<ListBox ItemsSource="{Binding Source={StaticResource NorthData},XPath=City,FallbackValue=BindingFailed}" Height="100" HorizontalAlignment="Left" Margin="128,144,0,0" Name="listBox1" VerticalAlignment="Top" Width="120" />
</Grid>
Using your code I modified the XPath a little bit, and removed the reference to the XSD which you didn't provide, and it worked:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<XmlDataProvider x:Key="NorthData" XPath="NorthwindDataSet/Customers">
<x:XData>
<NorthwindDataSet xmlns="">
<Customers>
<CustomerID>ALFKI</CustomerID>
<CompanyName>Alfreds Futterkiste</CompanyName>
<ContactName>Maria Anders</ContactName>
<ContactTitle>Sales Representative</ContactTitle>
<Address>Obere Str. 57</Address>
<City>Berlin</City>
<PostalCode>12209</PostalCode>
<Country>Germany</Country>
<Phone>030-0074321</Phone>
<Fax>030-0076545</Fax>
</Customers>
<Customers>
<CustomerID>ANATR</CustomerID>
<CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
<ContactName>Ana Trujillo</ContactName>
<ContactTitle>Owner</ContactTitle>
<Address>Avda. de la Constitucion 2222</Address>
<City>Mexico D.F.</City>
<PostalCode>05021</PostalCode>
<Country>Mexico</Country>
<Phone>(5) 555-4729</Phone>
<Fax>(5) 555-3745</Fax>
</Customers>
</NorthwindDataSet>
</x:XData>
</XmlDataProvider>
</Window.Resources>
<Grid>
<Label Content="{Binding XPath=Address
, FallbackValue=BindingFailed
, Source={StaticResource NorthData}}"
Height="28"
HorizontalAlignment="Left"
Margin="118,94,0,0" Name="label1"
VerticalAlignment="Top" Width="127" />
<ListBox ItemsSource="{Binding Source={StaticResource NorthData}
, XPath=City
, FallbackValue=BindingFailed}"
Height="100"
HorizontalAlignment="Left"
Margin="128,144,0,0"
Name="listBox1"
VerticalAlignment="Top"
Width="120" />
</Grid>
</Window>
You have to set the DataContext to your XML
<Window.Resources>
<XmlDataProvider x:Key="NorthData" Source="Northwind.xml" XPath="/Customers"/>
</Window.Resources>
<Grid DataContext="{StaticResource NorthData}">
<Label Content="{Binding XPath=Address,FallbackValue=BindingFailed,Source={StaticResource NorthData}}" Height="28" HorizontalAlignment="Left" Margin="118,94,0,0" Name="label1" VerticalAlignment="Top" Width="127" />
<ListBox ItemsSource="{Binding Source={StaticResource NorthData},XPath=City,FallbackValue=BindingFailed}" Height="100" HorizontalAlignment="Left" Margin="128,144,0,0" Name="listBox1" VerticalAlignment="Top" Width="120" />
</Grid>

WPF binding root element of xaml file does not work:

I was trying to bind a dataContext to a grid (xaml below)
<Grid .... DataContext="{Binding Path=NewFormViewModel}" > ...</Grid>
This binding did not work and I realized the getter for NewFormViewModel was never being called.
At this point in time, The grid was the root element of the xaml file.
I then placed a canvas inside the Grid and did binding on the canvas like :
<Grid ....>
<Canvas DataContext="{Binding Path=NewFormViewModel}">
....
</Canvas>
</Grid>
The data binding worked.
Next I tried to change the grid to a canvas and do databinding agiain like this:
<Canvas.... DataContext="{Binding Path=NewFormViewModel}" > ...</Canvas>
The binding stopped working again.
In the end I settled for a Grid nested inside a canvas:
<Canvas....>
<Grid DataContext="{Binding Path=NewFormViewModel}">
....
</Grid>
</Canvas>
The question is why did the binding on the root element of the xaml not work?
or Should I have not used a Canvas/Grid as a root element at all and used something like Page/UserControl?
EDIT
My logical tree looks somthing like this:
Window <- Data binding to object o
|
*
Frame <-Data binding to obect o inherited
|
*
Canvas/Grid <- Data binding to o.NewFormViewModel failed
|
*
Canvas/Grid <- Data binding to o.NewFormViewModel Succeeds
EDIT2:
broken xaml:
<Canvas x:Class="WPFEditors.NewForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Height="398" Width="377"
DataContext="{Binding Path=NewFormViewModel}"
>
<Grid >
<Label DataContext="Form Type" Height="31" HorizontalAlignment="Left" Margin="12,22,0,0" VerticalAlignment="Top" Width="92" />
<ComboBox Margin="148,22,6,347" ItemsSource="{Binding Path=FormTypes}" />
<Label Content="Description" Height="31" HorizontalAlignment="Left" Margin="12,58,0,0" VerticalAlignment="Top" Width="92" />
<Label Content="{Binding Path=Heading}" ToolTip="This is pulled from the Enum defined for FormTypes" Margin="148,59,6,309" />
<Label Content="Version" Height="31" HorizontalAlignment="Left" Margin="12,95,0,0" VerticalAlignment="Top" Width="92" />
<TextBox Text="Bind this later" Margin="148,97,6,270" Height="31" />
<Label Content="Approval Level" Height="31" HorizontalAlignment="Left" Margin="12,132,0,0" VerticalAlignment="Top" Width="92" />
<TextBox Height="31" Margin="148,134,6,233" Text="Bind this later" />
<Label Content="Number of Approvals" Height="31" HorizontalAlignment="Left" Margin="12,171,0,0" VerticalAlignment="Top" Width="130" />
<TextBox Height="31" Margin="148,173,6,194" Text="Bind this later" />
<Label Content="Heading" Height="31" HorizontalAlignment="Left" Margin="12,210,0,0" VerticalAlignment="Top" Width="130" />
<TextBox Height="31" Margin="148,212,6,155" Text="Bind this later" />
<Label Content="Static Data Id" Height="31" HorizontalAlignment="Left" Margin="12,247,0,0" VerticalAlignment="Top" Width="130" />
<TextBox Height="31" Margin="148,249,6,118" Text="Bind this later" />
<Label Content="{Binding Path=Errors}" Background="{Binding Path=Color}" Margin="12,325,6,6" BorderThickness="1" BorderBrush="#FF000019" />
<Button Content="Create" Margin="83,294,202,78" />
<Button Content="Create" Margin="181,294,104,78" />
<Button Content="Create" Margin="279,294,6,78" />
</Grid>
</Canvas>
In the above xaml the following line binds:
<Label Content="{Binding Path=Heading}"
even though Heading is inside a property of the viewmodel that this document inherits.
At this point I would have expected the line:
DataContext="{Binding Path=NewFormViewModel}"
to have changed the datacontext to NewFormViewModel which has no heading. All the remaining bindings fail.
If I change the beginning to :
<Canvas x:Class="NewForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Height="398" Width="377"
>
<Grid DataContext="{Binding Path=NewFormViewModel}" >
The binding to Heading fails and the rest of the bindings start to work. This is the behaviour that I was expecting initially.
This xaml is nested in this file :
<Window x:Class="WPFEditors.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding Path=Heading}" Height="743" Width="1177">
<StackPanel >
<Menu IsMainMenu="True" >
<MenuItem Header="New">
<MenuItem Header="New Form" Command="{Binding Path=MenuCommand}" />
</MenuItem>
<MenuItem Header="Edit Form" ItemsSource="{Binding Path=FormsAvailable}" />
<MenuItem Header="Edit Rules" />
</Menu>
<Frame NavigationUIVisibility="Hidden" Source="{Binding Path=CurrentPage}"
LoadCompleted="Frame_LoadCompleted"
DataContextChanged="Frame_DataContextChanged"
Name="frame">
</Frame>
</StackPanel>
</Window>
and the event handlers to copy the data context to the child are :
private void Frame_LoadCompleted(object sender, NavigationEventArgs e)
{
UpdateFrameDataContext();
}
private void Frame_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
UpdateFrameDataContext();
}
private void UpdateFrameDataContext()
{
var content = frame.Content as FrameworkElement;
if (content == null)
return;
content.DataContext = frame.DataContext;
}
The Binding in the root element should work IF there is something up in the control hierarchy (like a Window or UserControl) that holds (in its DataContext) the object owning the property you're querying (NewFormViewModel).

How to override parent datacontext in child panel

I want to override parent (grid) datacontext in one of the child panel (stackpanel),
such that any update in any of the stackpanel, xml file will get updated accordingly.
Initially I had XPath="/Data/MB" attribute in XmlDataProvider. So with this binding in only textbox 5 and 6 was successful.
Finally what I did is given below. This works fine.
<Grid>
<Grid.DataContext>
<XmlDataProvider x:Name="Credentials" Source="Credentials.xml"/>
</Grid.DataContext>
<StackPanel>
<TextBox Height="23" Name="textBox5" Width="188" Text="{Binding XPath=/Credentials/MessageBroker/Hostname}" />
<TextBox Height="23" Name="textBox6" Width="188" Text="{Binding XPath=/Credentials/MessageBroker/Port}"/>
</StackPanel>
<StackPanel>
<TextBox Height="23" Name="textBox9" Width="188" Text="{Binding XPath=/Credentials/Database/Server}" />
<TextBox Height="23" Name="textBox10" Width="188" Text="{Binding XPath=/Credentials/Database/Password}"/>
</StackPanel>
</Grid>
Here is Credentials.xml
<?xml version="1.0" encoding="utf-8"?>
<Credentials>
<MB>
<Hostname>145.111.227.222</Hostname>
<Port>5672</Port>
<UserName>Admin</UserName>
<Password>Admin</Password>
</MB>
<Database>
<Server>145.111.227.234</Server>
<UserID>Administrator</UserID>
<Password>password</Password>
</Database>
Is there any better way to do it?
Please let me know.

How to set selected value path to tab header text in a tab control in WPF

I am a little unclear on how I would set the SelectedValuePath of a TabControl to the text of the selected TabItems header. I feel like this should be fairly simple, and probably involves content.something but I have always been a bit confused about the Content property.
ItemTemplate — template for tab headers. Just add textblock with the same binding as in property SelectedValuePath.
<UserControl.Resources>
<XmlDataProvider x:Key="Employees" XPath="/Employees/*">
<x:XData>
<Employees xmlns="">
<Employee Name="Terry Adams" Type="FTE" EmployeeNumber="1" />
<Employee Name="Claire O&apos;Donnell" Type="FTE" EmployeeNumber="12345" />
<Employee Name="Palle Peterson" Type="FTE" EmployeeNumber="5678" />
<Employee Name="Amy E. Alberts" Type="CSG" EmployeeNumber="99222" />
<Employee Name="Stefan Hesse" Type="Vendor" EmployeeNumber="-" />
</Employees>
</x:XData>
</XmlDataProvider>
<DataTemplate x:Key="HeaderDataTemplate">
<TextBlock Text="{Binding XPath=#EmployeeNumber}" />
</DataTemplate>
<DataTemplate x:Key="ContentDataTemplate">
<TextBlock Text="{Binding XPath=#Name}" />
</DataTemplate>
</UserControl.Resources>
<TabControl ItemsSource="{Binding Source={StaticResource Employees}}"
ItemTemplate="{StaticResource HeaderDataTemplate}"
ContentTemplate="{StaticResource ContentDataTemplate}"
SelectedValue="12345"
SelectedValuePath="#EmployeeNumber"/>

Resources