I am working with binding an xml structure to a listbox. I am quite confused hoe to do this.How to put a datatemplate inside a datatemplate or i need to use a hirarchialdatatemplate...for example from the xml, I want to display the Make Name of the cars in a list box and i want to show the corresponding Suvs's as a tooltip or contextmenu.How to do this..please help..any input will be highly helpfull..my xml file structure is as given below
<XmlDataProvider x:Key="src">
<x:XData>
<Automobiles>
<Id>24</Id>
<Category>Cars</Category>
<MakeName>Audi</MakeName>
<Suvs>
<SuvId>Item1</SuvId>
<SuvId>Item1</SuvId>
<SuvId>Item1</SuvId>
<SuvId>Item1</SuvId>
</Suvs>
<IsPanel>1</IsPanel>
<IsFav>1</IsFav>
</Automobiles>
</x:XData>
</XmlDataProvider>
I modified your XML format to support multiple Automobile groups:
<XmlDataProvider x:Key="src">
<x:XData>
<Automobiles xmlns="">
<Automobile>
<Id>24</Id>
<Category>Cars</Category>
<MakeName>Audi</MakeName>
<Suvs>
<SuvId>audiItem1</SuvId>
<SuvId>audiItem2</SuvId>
<SuvId>audiItem3</SuvId>
<SuvId>audiItem4</SuvId>
</Suvs>
<IsPanel>1</IsPanel>
<IsFav>1</IsFav>
</Automobile>
<Automobile>
<Id>24</Id>
<Category>Cars</Category>
<MakeName>BMW</MakeName>
<Suvs>
<SuvId>bmwItem1</SuvId>
<SuvId>bmwItem2</SuvId>
<SuvId>bmwItem3</SuvId>
<SuvId>bmwItem4</SuvId>
</Suvs>
<IsPanel>1</IsPanel>
<IsFav>1</IsFav>
</Automobile>
</Automobiles>
</x:XData>
</XmlDataProvider>
I hooked up both a context menu and a tooltip.
Below is how I wired up the bindings:
<ItemsControl ItemsSource="{Binding Source={StaticResource src}, XPath=/Automobiles/Automobile}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu ItemsSource="{Binding XPath=Suvs}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="SUV ID: " />
<TextBlock Text="{Binding XPath=SuvId}" />
</StackPanel>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</StackPanel.ContextMenu>
<StackPanel.ToolTip>
<ListBox ItemsSource="{Binding XPath=Suvs/SuvId}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="SUV ID: " />
<TextBlock Text="{Binding InnerText, StringFormat={}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel.ToolTip>
<TextBlock Text="Make: " />
<TextBlock Text="{Binding XPath=MakeName}" />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
Related
I have this StackPanel in one grid on my form:
<StackPanel x:Name="panelWeelyBibleReading" Grid.Row="2" Grid.Column="0" Margin="2">
<Label>Bible Reading for Week:</Label>
<TextBox x:Name="textWeeklyBibleReading">PSALMS 60-68</TextBox>
</StackPanel>
<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">
<Label>Opening Song:</Label>
<ComboBox x:Name="comboSongOpen" ItemsSource="{StaticResource SongTitles}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.MaxWidth>
<Binding Path="ActualWidth"
ElementName="textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
</ComboBox>
</StackPanel>
Further down the form in a different grid I have this :
<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">
<Label>Closing Song:</Label>
<ComboBox x:Name="comboSongEnd" ItemsSource="{StaticResource SongTitles}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.MaxWidth>
<Binding Path="ActualWidth"
ElementName="panelWeeklyBibleReading.textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
</ComboBox>
</StackPanel>
Initially I tried using the same "textWeeklyBibleReading" for the MaxWidth in the second combo. But it doesn't work. No warnings. Just doesn't work. So I thought about applying a name to the previous StackPanel in teh hopes I could use it as some kind of access point. But it still doesn't work.
So my problem is that I need to set the MaxWidth on the second combo, which is in a different grid, but using the value that was calculated on the first grid combo. Am I making sense?
I would show the complete form markup if it helps.
You should edit to:
<ComboBox.MaxWidth>
<Binding Path="Width"
ElementName="textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
<Binding Path=Width, ElementName=textWeeklyBibleReading/>
cause there is no property such as ActualWidth, instead it should be Width. And there is no need to write container name panelWeeklyBibleReading, just write ElementName that you need.
Update:
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal" MaxWidth="{Binding Path=Width,
ElementName=textWeeklyBibleReading}">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
You should set MaxWidth of StackPanel of ComboBox cause outer StackPanel``(<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">) which contains your ComboBox automatically sets Width to the outer StackPanel to your ComboBox. So I suggest to bind Width of your ComboBox to its ItemTemplate. Cause ItemTemplate has Data/template, then it is better to bind Width of ComboBox to StackPanel located into your DataTemplate.
<phone:Pivot Title="Bank" x:Name="pivotBank"
ItemsSource="{Binding PivotItems}">
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding StrBankName}"/>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel>
<toolkit:ListPicker x:Name="listPickerAccountNumber" SelectionChanged="listPickerAccountNumber_SelectionChanged"
ItemsSource="{Binding listAccountDetails}" >
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding StrAccountNumber}" />
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
<toolkit:ListPicker.FullModeItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding StrAccountNumber}" />
</DataTemplate>
</toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>
<TextBlock Text="Account Detail"></TextBlock>
<TextBlock Name="textBlockAccountNumber" Text="{Binding StrAccountNumber}"></TextBlock>
<TextBlock Name="textBlockBalance" Text="{Binding DblBalance}"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
Above pivot control contains headers as bank names and pivot datatemplate contains list of accounts. I want to change the control values of textBlockAccountNumber and textBlockBalance on SelectedIndexChanged event of listPicker.
My question is, is there any way to find control by name from the pivot. I used INotifyPropertyChanged Interface and implemented event with handler but not able to get the rid of it.
I have The following structure
QPage class Object contains a List<List<QLine>>
QLine object contains List<Qword>
every list of words constructs a line and every list of lines consists a group(paragraph) and every list of paragraphs consists a page.
I want to bind the page to structure like this in XAML
<ListView>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock>
</TextBlock>
</StackPanel>
</StackPanel>
</ListView>
where each item of the ListView is a paragraph(List<QLine>) and each vertical stack panel holds an item of the List<QLine> and each item of the horizontal stack panel holds an item of the List<Qword> and the texblock is bound to Qword.text property. I have no idea how to do such binding from the XAML code.
Hopefully I did not miss some list but this should work. Basically it's a ListBox that hosts List<List<QLine>> (called it QPageList). Then you have ItemsControl that hosts each List<QLine> in vertical panel and finally there is another ItemsControl that hosts List<Qword> from QLine (called it QwordList) where each QWord is displayed as TextBlock on horizontal StackPanel
<!-- ItemsSource: List<List<QLine>>, Item: List<QLine> -->
<ListBox ItemsSource="{Binding QPageList}">
<ListBox.ItemTemplate>
<DataTemplate>
<!-- ItemsSource: List<QLine>, Item: QLine -->
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- ItemsSource: QLine.List<QWord>, Item: QWord -->
<ItemsControl ItemsSource="{Binding QwordList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- Item: QWord -->
<TextBlock Text="{Binding text}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
What you are looking for is ListView.ItemTemplate. Basically, you need to provide your list with a way to understand the nested data structure of your rows.
Here is a good tutorial to get you started on ItemTemplates.
Once your list has an item template then you just bind the ListView directly to your data source and that's it.
Hopefuly this will prove helpful. Taken from here
Authors (list)
- - Name
- - Books (list)
| - - Title
| - - Contents
Sample code :
<Window.Resources>
<DataTemplate x:Key="ItemTemplate1">
<StackPanel>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ItemTemplate2">
<StackPanel>
<TextBlock Text="{Binding Title}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource AuthorDataSource}}">
<ListBox x:Name="AuthorList" ItemTemplate="{DynamicResource ItemTemplate1}" ItemsSource="{Binding Authors }" >
<ListBox x:Name="BookList" DataContext="{Binding SelectedItem, ElementName=AuthorList}" ItemsSource="{Binding Books }" ItemTemplate="{DynamicResource ItemTemplate2}" />
<TextBlock x:Name="BookContent" DataContext="{Binding SelectedItem, ElementName=BookList}" Text="{Binding Contents }" />
</Grid>
Forward to what Alex is saying, it'd be a good idea to Encapsulate (If that's the correct word here) the object within classes, i.e.:
public class Page
{
public List<Paragraph> Paragraphs { get; set; }
}
public class Paragraph
{
public List<QWord> Sentences { get; set; }
}
public class Sentence
{
public List<QWord> Words { get; set; }
}
That'd help when you bind data in your XAML, i.e. if you look at the tutorial which Alex provided:
<TextBlock Text="Name: " />
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<TextBlock Text="{Binding Age}" FontWeight="Bold" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Mail}" TextDecorations="Underline" Foreground="Blue" Cursor="Hand" />
<TextBlock Text=")" />
Hope that helps you.
I'm currently trying to figure out how to show different types of objects in a GridView, look at this Pic for example:
the last element on the right side is different than the other elements, so if i bind an observablecollection to the GridView, how can i say that the last element is shown up in anohter layout.
currently I'm using this XAML-Code
<GridView x:Name="startView" ItemsSource="{Binding}" Grid.Column="1" Grid.Row="2" SelectionMode="None" Width="Auto">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="DetailTitle" Height="74" Text="{Binding Title}" />
<Image x:Name="Image" Height="Auto" Width="Auto" Margin="0" Stretch="None" Source="{Binding LocalCoverUrl}" Visibility="Collapsed" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" MaximumRowsOrColumns="2" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
and this Code in the Back:
ObservableCollection<Movie> recentlyStarted = await Api.RecentlyStarted(3);
startView.DataContext = recentlyStarted;
but I have currently no clue how to let the last element show up in a different style
The easy way would be to have the two types of object as different classes (e.g. MoviePicStyle + MoviePlainStyle. Then move your DataTemplate out of the GridView, so that each object is picked up by type,
e.g.
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModel:MoviePicStyle}">
<StackPanel>
<TextBlock x:Name="DetailTitle" Height="74" Text="{Binding Title}" />
<Image x:Name="Image" Height="Auto" Width="Auto" Margin="0" Stretch="None" Source="{Binding LocalCoverUrl}" Visibility="Collapsed" />
</StackPanel>
<DataTemplate DataType="{x:Type ViewModel:MoviePlainStyle}">
...Different View...
</DataTemplate>
</Window.Resources>
<GridView...
Use template selector property of gridview and depending upon the type of object select the template. I did the same in my project. you need to write your own DataTemplateSelector.
I referred below link
http://babaandthepigman.wordpress.com/2012/02/08/datatemplateselector-winrt/
I have the following problem:
i have some data loaded in my application, that need to be put in a tab control.
The data is in the format:
class objectType1
{
string property_1;
string prorerty_2;
}
class mainObject
{
string mainProperty_1;
string mainProperty_2;
List<objectType1> objectsList;
}
and all the data is loaded in an object of type
List<mainObject> myListofObjects
So far i managed to create the tabitems with respect to myListofObjects item
(ie if the list has 5 objects, 5 tabs are created with the header containing the information mainProperty_1 and mainProperty_2)
now i need to add the data contained in each objectsList into their respective tab...
the mainProperty_1 represents an image, which must be loaded...
<TabControl x:Name="_DataList" Margin="10">
<!-- Header -->
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Height="18" Source="{Binding mainProperty_1/>
<TextBlock Text="{Binding mainProperty_2}" Margin="2,0,0,0" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<!-- Content -->
<TabControl.ContentTemplate>
<DataTemplate x:Name="objectDataTemplate">
<Grid Margin="5">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding property_1}" ToolTip="{Binding property_2}" IsHitTestVisible="false" Stretch="Uniform"/>
</StackPanel>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
I pass the data to the tabcontrol in code behind with
_DataList.ItemsSource = myListofObjects;
this is not working for the content...
the header loads just fine (both image and the text...)
anyone has any idea how to do it?
Thanks a lot!
your ContentTemplate seems to be wrong:
<TabControl x:Name="_DataList" Margin="10">
<!-- Header -->
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Height="18" Source="{Binding mainProperty_1/>
<TextBlock Text="{Binding mainProperty_2}" Margin="2,0,0,0" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<!-- Content -->
<TabControl.ContentTemplate><!-- its bound to one mainObject -->
<DataTemplate x:Name="objectDataTemplate">
<!-- if you wanna bind to something from your objectsList you have to threat it like a list, cause it is :) -->
<ListBox Itemssource={Binding objectsList}>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type objectType1}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding property_1}" ToolTip="{Binding property_2}" IsHitTestVisible="false" Stretch="Uniform"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
1) Have you tried to connect to list via binding?
var b = new Binding("myListofObjects");
BindingOperations.SetBinding(_DataList, ItemsControl.ItemsSourceProperty, b);
2) If you're using binding, have you set appropriate DataContext?