Can a DataTemplate be placed inside another DataTemplate of different Template Structure? - c#

I want a DataTemplate for ListBox having the ItemsSource as Collection of Borders. Inside each Border i want to display another ListBox containg set of some items having its own ItemsSource.
But, when i try to acheive this structure i am not able to populate any data.
My XAML code -
<Grid x:Name="RightPanel" Grid.Column="2" Background="Beige">
<Border BorderBrush="Black" Margin="4" BorderThickness="1.5">
<ScrollViewer Margin="2" Focusable="False">
<ListBox x:Name="MainRightListBox" ItemsSource="{Binding ListBoxCollection,Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBox x:Name="ChildListBox" ItemsSource="{Binding CurrentPage.ClonedVectorImages,Mode=TwoWay}" SelectedItem="{Binding ImageVectorSelected}" BorderBrush="Transparent" Background="Transparent">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="canvas" Background="Transparent" Orientation="Horizontal" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete" CommandParameter="{Binding}"
Command="{Binding PlacementTarget.Tag.DataContext.DeleteCloneCommand, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}, Mode=FindAncestor}}"/>
</ContextMenu>
</StackPanel.ContextMenu>
<Viewbox Width="35" Height="35" >
<Canvas Width="35" Height="35">
<Canvas>
<Path Fill="#ffda2526" Data="F1 M 0.000,112.500 C 0.000,50.369 50.368,0.000 112.500,0.000 C 174.632,0.000 225.000,50.369 225.000,112.500 C 225.000,174.633 174.632,225.000 112.500,225.000 C 50.368,225.000 0.000,174.633 0.000,112.500 Z" Height="30.667" Stretch="Fill" Width="31"/>
<TextBlock x:Name="tb1" Text="{Binding CountId}" Foreground="WhiteSmoke" FontSize="20" FontFamily="Arial Bold" Height="20" RenderTransformOrigin="1.588,1.224" Canvas.Left="9.322" Canvas.Top="3.335"></TextBlock>
</Canvas>
</Canvas>
</Viewbox>
<TextBox Text="Enter Text Here" Height="20" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</Border>
</Grid>

"Can a DataTemplate be placed inside another DataTemplate of different Template Structure?"
The answer is yes, it can. Your XAML structure is fine.
But what possibly wrong is binding path/expression used. You need to be aware that DataContext of the inner ListBox (the one inside DataTemplate) is corresponding item in ListBoxCollection. So if that item mentioned before has property CurrentPage.ClonedVectorImages, this way of binding should work fine to populate the inner ListBox :
<ListBox x:Name="ChildListBox"
ItemsSource="{Binding CurrentPage.ClonedVectorImages,Mode=TwoWay}"
........>

You need to put DataTemplates in resources with the corresponding keys, because otherwise an exception may occur:
Markup.IStyle.Connector.Connect error
This is bug of studio, which is described as follows link:
A good way to look at this problem “Templating is like parentheses, quoting parentheses” the Template XAML is not created but saved and run later. The bug is therefore: We have a problem with nested parentheses.
In any case as I think, should be avoided nesting templates and use him via resources, it will be easier and clearer.

Related

listbox checkbox not binding to its source

I need help binding my checkbox list in listbox which is in a popup box. My XAML code is as follows
<Popup Name="popUser" Placement="Bottom" PlacementTarget="{Binding ElementName=BtnUserFilter}" StaysOpen="False" Height="100" VerticalAlignment="Top">
<Border Background="White" BorderBrush="Gray" BorderThickness="1,1,1,1">
<StackPanel Margin="5,5,5,15">
<StackPanel Orientation="Horizontal" Margin="0,0,0,20">
<Button Margin="0,0,0,0" Name="BtnSelectAll" Click="BtnSelectAll_Click">
<Button.Template>
<ControlTemplate>
<TextBlock Text="Select All" Foreground="Blue" Cursor="Hand" />
</ControlTemplate>
</Button.Template>
</Button>
<Button Margin="10,0,0,0" Name="BtnUnselectAll" Click="BtnUnselectAll_Click">
<Button.Template>
<ControlTemplate>
<TextBlock Text="Select None" Foreground="Blue" Cursor="Hand" />
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
<ListBox x:Name="lstUser" BorderThickness="0" Height="100" ItemsSource="{Binding Userlists, RelativeSource={RelativeSource AncestorType=local:MainWindow}}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=IsChecked, UpdateSourceTrigger=PropertyChanged}"
Content="{Binding Path=UserIL, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Border>
</Popup>
The code in viewmodel to which the listbox is bound to is
Dim test = (From c In Users Select New With {Key c.User}).Distinct
Dim Cnt As Integer
For Cnt = 0 To test.Count - 1
UserLists.Add(New UserList(Of String) With {.IsChecked = True, .UserIL = test(Cnt).User})
Next
The code populates all the users in the UserList Variable but doesn't show up in the ListBox. Am I not binding the checkbox properly? Ideas?
Make sure that UserLists is an ObservableCollection because a regular list does not propagate changes made to its content to the UI.
Furthermore I would suspect you have a typo in your xaml by refering to the UserLists as Userlists (note case sensitivity)
For purposes of resolving backing types, WPF XAML is case sensitive by
the same rules that the CLR is case sensitive. Object elements,
property elements, and attribute names must all be specified by using
the sensitive casing when compared by name to the underlying type in
the assembly, or to a member of a type.

Creating collections of arbitrarily positioned controls in WPF

I have a simple Border and Grid that is positioned within a Canvas container in WPF. The position of the control changes during runtime hence why it resides in the canvas.
The XAML for the control looks something like this:
<Border Name="PopupArea"
Width="130"
Height="150"
BorderBrush="Black"
BorderThickness="2"
CornerRadius="5">
<Border.Background>
<SolidColorBrush Opacity="0.5" Color="Black" />
</Border.Background>
<Grid>
<StackPanel>
<Border HorizontalAlignment="Center">
<Border.Effect>
<DropShadowEffect />
</Border.Effect>
<TextBlock FontWeight="Bold" Style="{StaticResource SmallWhiteFont}">HELLO WORLD</TextBlock>
</Border>
</StackPanel>
</Grid>
</Border>
However I now need to be able to create a Collection of the above control which I create and destory as required at runtime in code.
My questions are :
A. What is the best way to compose my XAML to create multiple instances of the above control through code? Do I just declare a ContentControl in the resources?
B. Assuming I am correct and a resource template is required. How do I actually use it to create multiple instances of the control in code?
Within XAML I would use an ItemTemplate.
Then I would bind ItemsSource to some observable collection on my viewmodel.
Here's an example taken from MSDN:
<ListBox Width="400" Margin="10"
ItemsSource="{Binding Source={StaticResource myTodoList}}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=TaskName}" />
<TextBlock Text="{Binding Path=Description}"/>
<TextBlock Text="{Binding Path=Priority}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
NOTE:
It is more common to define a DataTemplate in the resources section so it can be a reusable object.
<ListBox Width="400" Margin="10"
ItemsSource="{Binding Source={StaticResource myTodoList}}"
ItemTemplate="{StaticResource myTaskTemplate}"/>

retrieving binded text from xaml in c#

I have my xaml code as :
<ListBox x:Name="SecondListBox" Margin="0,0,-12,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432" Height="78">
<toolkit:ToggleSwitch Name="toggle3" Header="{Binding name}" Height="120" HorizontalAlignment="Left" Margin="35,20,0,0" VerticalAlignment="Center" Width="440" Content="{Binding descrip}" Checked="toggleSwitch1_Checked" Unchecked="toggleSwitch1_Unchecked" Tap="toggleSwitch1_Tap"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PivotItem>
Now i want to retrieve toggleswitch(toggle 3)'s header text in c# code. How can that be done?
When you create a data binding like you did, it should automatically update the variable you bound it to, name
Assuming you have a proper collection to serve as the ItemsSource Binding
the xaml would write as follows:
<ListBox x:Name="SecondListBox" Margin="0,0,-12,0" ItemsSource="{Binding Path=ItemsCollection}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432" Height="78">
<toolkit:ToggleSwitch Name="toggle3" Header="{Binding Name,Mode=TwoWay}" Height="120" HorizontalAlignment="Left" Margin="35,20,0,0" VerticalAlignment="Center" Width="440" Content="{Binding descrip}" Checked="toggleSwitch1_Checked" Unchecked="toggleSwitch1_Unchecked" Tap="toggleSwitch1_Tap"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You'll have to provide a property named ItemsCollection of type IEnumerable<TModel> in your DataContext
where TModel class shouldcontain Name property
This should put you on the right path to access elements inside of ItemTemplate.Probably that's what your looking for.
http://dotbay.blogspot.in/2009/09/accessing-controls-in-wpf-itemtemplate.html

Adding a List of Songs to a ListBox

i am trying to make my own mediaplayer for Windows Phone 7 and for the first step, i want to display a List of all songs in my media library to select them.
As i understood the ListBox, i just have to name the texblocks like the attributes of my class, which would be "Song"
<ListBox FontSize="30" Name="songListGUI" Height="330" Margin="0,120,0,0">
<Button Width="430" Height="60" BorderThickness="0" Margin="0" >
<Button.Content>
<StackPanel Orientation="Horizontal" Width="420" Height="auto">
<TextBlock Name="Name" Text="{Binding Name}" FontSize="22"></TextBlock>
<TextBlock Text=" - " FontSize="22"></TextBlock>
<TextBlock Name="Artist" Text="{Binding Artist}" FontSize="22"></TextBlock>
</StackPanel>
</Button.Content>
</Button>
</ListBox>
And now i think, i should handle my list of songs to the GUI and i try to do that with:
songListGUI.ItemsSource = songs;
But then i get a "InvalidOperationException" - Items collection must be empty before using ItemsSource.
I found several problems like this, and they all created a new class, to display this content. But i would like to stick with the song class, as it comes in quite handy :/
Do you know what i am doing wrong here?
edit:
i just found the solution. Don´t know exactly why, but this change in the .xaml made my da :):
<ListBox FontSize="30" Name="songListGUI" Height="330" Margin="0,120,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Width="430" Height="60" BorderThickness="0" Margin="0" >
<Button.Content>
<StackPanel Orientation="Horizontal" Width="420" Height="auto">
<TextBlock Name="Name" Text="{Binding Name}" FontSize="22"></TextBlock>
<TextBlock Text=" - " FontSize="22"></TextBlock>
<TextBlock Name="Artist" Text="{Binding Artist}" FontSize="22"></TextBlock>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Anybody could explan this to me?
ListBox is an ItemsControl. The content of an ItemsControl maps to the Items property. So by doing this:
<ListBox>
<SomeContent/>
</ListBox>
you're setting the Items property to <SomeContent/>. Since you aren't allowed to set the Items property and the ItemsSource property you get an exception.
When you do this:
<ListBox>
<ListBox.ItemTemplate>...</ListBox.ItemTemplate>
</ListBox>
You're not setting the content you're setting an attribute of the ListBox so there's no conflict.

ItemRealized event does not fire

I wanna create a infinite longlistselector, but my event ItemRealized does not fire. i have create view model so i can generate an observable collection, and everything sees to be working fine when i monitoring the main class, i'm sure that it is not empty, but my problem is that i can not populate the longlistselector
<phone:PhoneApplicationPage.Resources>
<vm:GoogleView x:Key="viewModel"/>
</phone:PhoneApplicationPage.Resources>
longlistselector
<phone:LongListSelector ItemRealized="m_ListBoxGoogle_ItemRealized" Name="m_ListGoogle" HorizontalAlignment="Center" Height="410" Margin="0,120,0,0"
ItemsSource="{Binding GoogleCollection}"
DataContext="{StaticResource viewModel}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Button Tag="{Binding GoogleID}" Style="{StaticResource NoVisualTextButton }" toolkit:TiltEffect.IsTiltEnabled="True" Click="OnListBoxItemClick" Margin="-10,0,0,0">
<StackPanel Orientation="Horizontal" Margin="0,3,0,0" Height="auto" Width="450">
<Border BorderThickness="1" Width="62" Height="62" BorderBrush="#00aef0" Background="#00aef0">
<Image Height="60" Width="60" Source="{Binding GoogleImagePath}"/>
</Border>
<StackPanel Width="350" HorizontalAlignment="Center" Margin="12,0,0,0" >
<TextBlock Text="{Binding GoogleDisplayName}" TextWrapping="NoWrap" Style="{StaticResource PanoramaItemTextStyle }" FontSize="24" />
<TextBlock Text="{Binding GoogleObjectType}" TextWrapping="NoWrap" Style="{StaticResource PanoramaItemTextStyle }" FontSize="20" />
</StackPanel>
</StackPanel>
</Button>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
i'm really stuck guys, please help me
Try these things for I believe its a binding issue:
Debug and put a breakpoint in the GoogleView constructor and verify
it is being instantiated.
If it is being instantiated verify the data you are binding to exists within the class.
If everything instantiated, try binding to the collection as TwoWay binding mode.
If that doesn't work try binding to the data in another control to verify things are working properly.

Categories