When I tap on listBox item i get a SubItem in "selectionChanged" event. I need to get Title as well. How i can achieve it?
public class Data
{
public string Title { get; set; }
public List<SubItem> SubItems { get; set; }
public Data()
{
SubItems = new List<SubItem>();
}
}
<phone:LongListSelector ItemsSource="{Binding DataCollection}" Grid.Row="0">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" Padding="5" />
<TextBlock Text="{Binding ImageSource}" Padding="5"/>
</StackPanel>
<ListBox ItemsSource="{Binding SubItems}" SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding SubItemTitle}" Margin="0,0,12,0" Padding="10" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
In the SelectionChanged event, you can retrieve your ListBox by casting the sender parameter. From there, you can retrieve your Data object by casting the datacontext:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = (ListBox)sender;
var data = (Data)listBox.DataContext;
System.Diagnostics.Debug.WriteLine(data.Title);
}
Under your selectionChangedevent try this :
string text = (listBox.SelectedItem as ListBoxItem).Content.ToString(); //listBox is the name of the Listbox
a better reference could be this:
Getting selected item string from bound ListBox
Hope it helps!
Related
I want to repeat the Border element inside the outer WrapPanel:
<WrapPanel x:Name="filterWrapper" Orientation="Horizontal">
<Border>
<WrapPanel>
<TextBlock Text="{Binding FilterName}"/>
<TextBlock Text="x"/>
</WrapPanel>
</Border>
</WrapPanel>
This is the depending class:
public class FilterField
{
public String FilterName { get; set; }
}
I have a collection of FilterField objects, which should result in:
<WrapPanel x:Name="filterWrapper" Orientation="Horizontal">
<Border>
<WrapPanel>
<TextBlock Text="Test_1"/>
<TextBlock Text="x"/>
</WrapPanel>
</Border>
<Border>
<WrapPanel>
<TextBlock Text="Test_2"/>
<TextBlock Text="x"/>
</WrapPanel>
</Border>
<Border>
<WrapPanel>
<TextBlock Text="Test_3"/>
<TextBlock Text="x"/>
</WrapPanel>
</Border>
</WrapPanel>
How can I achieve this?
You can use the ItemsControl to display a collection of items with a specific template in a specific Panel:
<ItemsControl ItemsSource="{Binding Items}">
<!-- Place all items in a WrapPanel -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel x:Name="filterWrapper" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- Define the look of each item -->
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type wpfapp1:FilterField}">
<Border>
<WrapPanel>
<TextBlock Text="{Binding FilterName}"/>
<TextBlock Text="x"/>
</WrapPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The DataTemplate you define in ItemsControl.ItemTemplate gets applied to all items in the source collection, and each item gets added in the ItemsControl.ItemsPanel that you define, here a WrapPanel.
This is assuming you have a a collection Items of type List<FilterField> in your view model, like this:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = new MyViewModel();
}
}
public class MyViewModel {
public List<FilterField> Items { get; set; } = new List<FilterField> {
new FilterField() { FilterName = "Test_1"},
new FilterField() { FilterName = "Test_2"},
new FilterField() { FilterName = "Test_3"},
};
}
public class FilterField {
public string FilterName { get; set; }
}
I want to build a dynanmic list of buttons (or whatever element is in the template, doesn't really matter.., my XAML is:
<Button Content="Add New Button" VerticalAlignment="Center" Click="AddNewButton" HorizontalAlignment="Center"/>
<ItemsControl ItemsSource="{Binding ButtonsList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Height="40" MinWidth="40" Content="{Binding Name}" Margin="2"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
My code behind looks like this:
public MainWindow()
{
InitializeComponent();
ButtonsList = new ObservableCollection<ShortcutButton>();
}
public class ShortcutButton
{
public string Name { get; set; }
}
public ObservableCollection<ShortcutButton> ButtonsList { get; set; }
private void AddNewButton(object sender, RoutedEventArgs e)
{
tblock.Text += "Button Clicked" + Environment.NewLine;
ButtonsList.Add(new ShortcutButton() { Name = "New button title" });
}
When I debug, I can see that objects are being added to the ButtonsList Observable Collection, but it does not update in the bound WrapPanel in ItemsControl.. What am I doing wrong?
Your Binding is incorrect, by default it will try to search for a property named ButtonList in the DataContext. To bind your ItemsSource to your ButtonList defined in the MainWindow you should change the RelativeSource like this:
<ItemsControl ItemsSource="{Binding Path=ButtonsList, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}">
I have a ListBox which creates a TextBlock for every item in my Dictionary and I need to create a click event and have the possibility to get anything from the TextBlock (Tag in example).
Is this even possible? I found many similar questions, but nothing that would work for me.
My ListBox:
<ListBox x:Name="listbox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Tag="{Binding Path=Key}"
Text="{Binding Path=Value.ImieNazwisko}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
To simplify things lets say your dictionary is some thing like this :
public Dictionary<string,MyItem> MyDictionary { get; set; }
and your model :
public class MyItem
{
public string ImieNazwisko { get; set; }
}
and you set the ListBox ItemSource from the code behind like this :
InitializeComponent();
MyDictionary = new Dictionary<string, MyItem>()
{
{"key1",new MyItem() {ImieNazwisko = "one"} },
{"key2",new MyItem() {ImieNazwisko = "two"} }
};
Listbox.ItemsSource = MyDictionary;
You could simply handle the MouseDown event and retrieve the Tag property from the sender:
<ListBox x:Name="Listbox" Margin="225,0,0,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Tag="{Binding Path=Key}" Text="{Binding Path=Value.ImieNazwisko}" MouseDown="UIElement_OnMouseDown"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
the handler
private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
{
var tag=(sender as TextBlock).Tag;
}
I'm attempting to databind to a Windows Phone 8 Toolkit Expander view with the following XAML and C# class. I know that the DataContext is set properly because the Headers have the proper text. However, the rest of the items aren't set properly (except for the ExpanderTemplate)
<phone:PanoramaItem Header="Skill Sheet">
<ListBox Name="SkillSheet" ItemsSource="{Binding}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<toolkit:ExpanderView Header="{Binding}"
ItemsSource="{Binding}"
IsNonExpandable="False">
<toolkit:ExpanderView.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding groupName}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" LineHeight="{StaticResource LongListSelectorGroupHeaderFontSize}" />
</DataTemplate>
</toolkit:ExpanderView.HeaderTemplate>
<toolkit:ExpanderView.ExpanderTemplate>
<DataTemplate>
<TextBlock Text="Test" />
</DataTemplate>
</toolkit:ExpanderView.ExpanderTemplate>
<!--This is the area that is not getting databound-->
<toolkit:ExpanderView.ItemTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding skillNames}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding skill}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</toolkit:ExpanderView.ItemTemplate>
</toolkit:ExpanderView>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</phone:PanoramaItem>
And here are the classes that the XAML is getting bound to:
public class TreeMapSkill
{
public string skill { get; set; }
}
public class TreeMapping
{
public string groupName { get; set; }
public List<TreeMapSkill> skillNames { get; set; }
public TreeMapping()
{
skillNames = new List<TreeMapSkill>();
}
}
public class TreeMappingList
{
public List<TreeMapping> mapping { get; set; }
public TreeMappingList() { }
public TreeMappingList(Dictionary<string, List<string>> map)
: base()
{
this.mapping = new List<TreeMapping>();
foreach (string key in map.Keys)
{
TreeMapping tMap = new TreeMapping();
tMap.groupName = key;
foreach (string val in map[key])
tMap.skillNames.Add(new TreeMapSkill() { skill = val });
this.mapping.Add(tMap);
}
}
The Dictionary in the constructor is simply a list of skills associated to a specific group. I can also provide a sample object if it's needed for additional reference.
Why are you adding a ListBox inside the Expander's ItemTemplate? It is already a controls collection so you don't need a ListBox in there. Just put your DataTemplate inside.
<toolkit:ExpanderView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding skill}" />
</DataTemplate>
</toolkit:ExpanderView.ItemTemplate>
The second thing is you need to specify the property path on the binding of the ItemSource property for the expander.
<toolkit:ExpanderView Header="{Binding}"
ItemsSource="{Binding skillNames}"
IsNonExpandable="False">
I use this code to create the ListBox in the XAML :
<ListBox Margin="20,96,20,20" ItemsSource="{Binding Items}" Name="ResultsListBox" SelectionChanged="ResultsListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And this is the code that i insert the strings(list is a List of String):
ResultsListBox.ItemsSource = list;
Now i want the possible to create this listbox with array of items that contain:
string name
string id
string imageurl
Can i combine the this to kind of lists?
Create a class like this
public class SomeClass
{
string name { get; set; }
string id { get; set; }
string imageurl { get; set; }
}
Then change your xaml like this
<ListBox Margin="20,96,20,20" ItemsSource="{Binding Items}" Name="ResultsListBox" SelectionChanged="ResultsListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding name}" />
<TextBlock Text="{Binding id}" /> <!-- ignore id if you don't want -->
<TextBlock Text="{Binding imageurl}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now, generate a collection or list to bind to the listbox
List<SomeClass> list = new List<SomeClass>();
list.Add(new SomeClass() { name = "some name", id = "some id", imageurl = "some url" });
list.Add( .....);
ResultsListBox.ItemsSource = list;