I've got for example ListBox with two TextBlocks like this:
<ListBox Name="listboxNews"
SelectionChanged="listboxNews_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Width="400"
Height="70">
<TextBlock Text="{Binding Title}" name="title" />
<TextBlock Text="{Binding Description}" name="desc" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And as you can see, I've got listboxNews_SelectionChanged method, in which i need to select Text of first TextBlock (if posibble by name so it will be independent on order of textblocks), but this one, which I select. For example if first item has title "Item 1" and second "Item 2" and I click on second one, i need to get "Item 2". I was trying something with listboxNews.Items, but i guess this is not correct. Thanks for help.
The SelectedItem property will hold the currently selected object. You can just cast that and take the Title property.
Try this code:
private void listboxNews_SelectionChanged(object sender, SelectionChangedEventArgs e) {
var current = listboxNews.SelectedItem as MyObjectType;
MessageBox.Show(current.Title);
}
Change MyObjectType with the type of your object.
This is a copy and paste out of a working Windows Phone 8 solution.
This was also tested successfully in WPF.
private void ListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
foreach (UIElement item in (sender as ListBox).Items)
{
if ((sender as ListBox).SelectedItem == item)
{
foreach (UIElement InnerItem in (item as StackPanel).Children)
{
if ((InnerItem is TextBlock) && (InnerItem as TextBlock).Name.Equals("title"))
{
MessageBox.Show((InnerItem as TextBlock).Text);
}
}
}
}
}
Related
I created a ListPickerFlyout and I would like, through a button, select an item from the list.
In XAML I have done so:
<Button x:Name="BottoneFiltraCittaNotizie" Click="BottoneFiltraCittaNotizie_Click" Style="{StaticResource ButtonSearchStyle}" Grid.Row="0" BorderBrush="{x:Null}" Foreground="Gray" Margin="0,-12,0,0">
<Button.Flyout>
<ListPickerFlyout ItemsSource="{Binding Source={StaticResource Museum}}">
<ListPickerFlyout.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding NomeProvincia}" HorizontalAlignment="Left"/>
</StackPanel>
</DataTemplate>
</ListPickerFlyout.ItemTemplate>
</ListPickerFlyout>
</Button.Flyout>
</Button>
in c # I want to recover the selected item, and then do some operations. MSDN there is SelectedItem instead I can not find it, and I said that does not exist, how could I do?
private void BottoneFiltraCittaNotizie_Click(object sender, RoutedEventArgs e)
{
Regioni region = ListPickerFlyout.SelectedItem as Regioni; //ERROR!!
string regione = region.NomeRegione;
var GruppiAllNEWS = NotizieFB.Where(x => x.TAG.Contains(regione)).OrderBy(x => x.Data).Reverse();
}
Add a property of your object to your view model (or code behind, or whatever you use as your datacontex), and then add a binding to that on that list.
Assuming you have public MyObject my_object {get;set;} in your datacontext, you should have on your xaml something like:
<ListPickerFlayout ...
SelectedItem = {binding my_object;} />
This way it knows that whatever is selected, will be that object in the data context, and you can access it from your code, by simply using the above property:
public class SomeClass {
// this is your code behind file
public MyObject my_object {get;set;}
// this is where you go when you hit the button
OnButtonClick(sender, event) {
//my_object is accessible here. Assuming it has a DoSomething method, you can:
my_object.DoSomething();
}
}
Alternatively, as this msdn suggests, you won't have to bind to a property (i would, since i'll try to do it in a MVVM way), and all you'll have to do is cast the sender and use it's selected item, something along:
void PrintText(object sender, SelectionChangedEventArgs args)
{
// get your object with the cast, and then get it's item
ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);
// then you can use it like:
tb.Text = " You selected " + lbi.Content.ToString() + ".";
}
I want to define a double click even on a TreeView so that I will be able to know which item in the TreeView was selected and to get his title.
The way I try to get it's title gets me "MyProject.MenuItem".
How can I refer to the selected item on the tree, make sure it's not the root, and get it's title?
What I did:
<TreeView Name="trvMenu" HorizontalAlignment="Left" Height="312" VerticalAlignment="Top" Width="200" MouseDoubleClick="TreeView_MouseDoubleClick" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:MenuItem}" ItemsSource="{Binding Items}">
<TextBlock Text="{Binding Title}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
The MessageBox shows "MyProject.MenuItem", what I want to do is not show a messagebox, but to get the title of the selected treeview item, after checking it is not the root
private void TreeView_MouseDoubleClick(object sender, RoutedEventArgs e)
{
if (sender is TreeViewItem)
if (!((TreeViewItem)sender).IsSelected)
return;
TreeViewItem tviSender = sender as TreeViewItem;
MessageBox.Show(trvMenu.SelectedItem.ToString());
}
Change your double click handler like shown below. Instead of calling ToString it accesses the Title property of your MenuItem item class.
private void TreeView_MouseDoubleClick(object sender, RoutedEventArgs e)
{
var menuItem = trvMenu.SelectedItem as MyProject.MenuItem;
if (menuItem != null)
{
MessageBox.Show(menuItem.Title);
}
}
I have a ListBox with binding, when i add Items it works perfect but if i try to remove the items with contextMenu it doesnt work.
Here is what i try so far ListBox Xaml Code
<ListBox Name="lstPersons"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" Margin="126,-228,2,-242">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu Name="PersonContext">
<toolkit:MenuItem Name="PersonDelete" Header="Delete" Click="DeletePerson_Click"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Name="btnKellnerName"
Text="{Binding _PersonName}"
FontSize="35"
FontFamily="Portable User Interface"/>
<TextBlock Name="btnPosition"
Text="{Binding _PersonPosition}"
FontSize="22"/>
<TextBlock Name="lblUhrzeit"
Text="{Binding _CreationDate}"
FontSize="18"/>
<TextBlock Name="Space" Text=" "/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And the Binding Class Code
public class Person
{
public string _PersonName { get; set; }
public string _PersonPosition { get; set; }
public string _CreationDate { get; set; }
}
When i add items like this
ObservableCollection<Person> personList = new ObservableCollection<Person>();
personList.Add(new Person {
_PersonName = "Tom",
_PersonPosition = "Bla",
_CreationDate = "33"
});
this.lstPerson.ItemSource = personList;
it works pefect! Now i Want to remove a selected Item with the ContextMenu like this
private void DeletePerson_Click(object sender, RoutedEventArgs e)
{
int indexPerson = lstPerson.SelectedIndex;
personList.RemoveAt(indexPerson);
}
but it doesnt work. Does Anybody have an Idea what im making wrong? Thanks
Ok Guys i have now the Solution the Problem was the value of SelectedIndex now ive got the right Value. First ive put the ContextMenu inside ListBoxItemTemplate/StackPanel
Code Behind:
private void DeletePerson_Click(object sender, RoutedEventArgs e)
{
try {
var selectedListBoxItem = listBox.ItemContainerGenerator.ContainerFromItem(((MenuItem) sender).DataContext) as ListBoxItem;
var selectedIndex = listBox.ItemContainerGenerator.IndexFromContainer(selectedListBoxItem);
_personList.RemoveAt(selectedIndex);
}
catch( Exception ex ) { MessageBox.Show(ex.Message); };
}
In addition to what Joan said, you can also do this in Xaml like this:
<ListBox ItemsSource={Binding personList}
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" Margin="126,-228,2,-242">
<toolkit:ContextMenuService.ContextMenu>
</ListBox>
You should read how to use Bindings and the MVVM-Model. It's pretty convenient for stuff like this.
Here are some links:
http://channel9.msdn.com/Events/MIX/MIX10/EX14
http://channel9.msdn.com/Events/MIX/MIX11/OPN03
Don't get discouraged. It's a bit of learning at the beginning, but it's totally worth it. I also had some problems with displaying lists, before I started doing everything with MVVM using Laurent Bugnions' MvvmLight package.
try this:
private void DeletePerson_Click(object sender, RoutedEventArgs e)
{
System.Collections.IList pathRemove;
pathRemove = lstPerson.SelectedItems;
if(pathRemove.Count != 0)
{
for (int i = pathRemove.Count - 1; i >= 0; i--)
{
lstPerson.Remove((Person)pathRemove[i]);//multiple deletes
}
}
}
Try to add this when the form is initialized:
lstPersons.ItemsSource = personList ;
How to: Create and Bind to an ObservableCollection
It appears that the problem is due to selected item
The key is setting the PreviewMouseRightButtonDown event in the
correct place. As you'll notice, even without a ContextMenu right
clicking on a ListViewItem will select that item, and so we need to
set the event on each item, not on the ListView.
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<EventSetter Event="PreviewMouseRightButtonDown"
Handler="OnListViewItemPreviewMouseRightButtonDown" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Menu Item">Item 1</MenuItem>
<MenuItem Header="Menu Item">Item 2</MenuItem>
</ContextMenu>
</ListView.ContextMenu>
<ListViewItem>Item</ListViewItem>
<ListViewItem>Item</ListViewItem>
<ListViewItem>Item</ListViewItem>
<ListViewItem>Item</ListViewItem>
<ListViewItem>Item</ListViewItem>
<ListViewItem>Item</ListViewItem>
</ListView>
.
private void OnListViewItemPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
Trace.WriteLine("Preview MouseRightButtonDown");
e.Handled = true;
}
wpf listview right-click problem
Why don't use binding for all.
Bind item source as ObservableCollection blabla
Bind Selecteditem as XXXX
Use command for your button and when you want remove an item do :
blabla.remove(SelectedItem);
I'm using a ListBox to display all values contained in Dictionary<> object:
<ListBox Height="519" x:Name="ContactsListBox" Width="460" Margin="0,0,0,0" SelectionChanged="ContactsListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Key}" Margin="5" Foreground="{StaticResource PhoneAccentBrush}"/>
<TextBlock x:Name ="LastNameData" Text="{Binding Value}" Margin="20, 0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Content is filled by the following code:
Dictionary<long, Contact> contacts = new Dictionary<long, Contact>();
this.ContactsListBox.ItemsSource = contacts;
Now, I would like to 'know' which specific "Contact" in ListBox is currently selected, either by knowing its Key, or just by extracting value from "LastNameData" TextBlock.
I tried doing something like that, but obviosly it doesn't work:
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lb = this.ContactsListBox.SelectedItem as ListBox;
this.Test_SomeOtherTextBlock.Text = lb.ToString();
}
I would really appreciate your help!
you can even do the follwing:
<ListBox Height="519" x:Name="ContactsListBox" Width="460" Margin="0,0,0,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Key}" Margin="5"/>
<TextBlock x:Name ="LastNameData" Text="{Binding Value}" Margin="20, 0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid DataContext="{Binding ElementName=ContactsListBox, Path=SelectedItem}" Margin="0,470,0,0">
<TextBlock Text="{Binding Value}"/>
</Grid>
So you don't need code behind...
BR,
TJ
There are several problems:
In Xaml you probably don't want to display the class name, but a reasonable string, for example:
<TextBlock x:Name ="LastNameData" Text="{Binding Value.LastName}" Margin="20, 0" />
In the selection processing the selected item is KeyValuePair<...>. You could easily find it yourself, if you looked at the returned type in debugger. (Should be kind of a reflex for a programmer, hence a questions like above should never appear :))
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
KeyValuePair<long, Contact> kv = (KeyValuePair<long, Contact>)this.ContactsListBox.SelectedItem;
Contact c = (Contact)kv.Value;
Debug.WriteLine(c.LastName);
}
Your code is good, using ListBox.SelectedItem is the right approach.
I think the problem is that you should cast it as ListBoxItem, not ListBox. And also to get to its value using DataContext, so something like along these lines (not tested, I'm not sure about accessing DataContext value in the last line):
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBoxItem lbi = this.ContactsListBox.SelectedItem as ListBoxItem;
var dataContext = lbi.DataContext;
this.Test_SomeOtherTextBlock.Text = dataContext.Value.ToString();
}
Try this it works for me, will help you to...
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox ContactListBox = sender as ListBox;
ListBoxItem listBoxItem = ContactListBox .ItemContainerGenerator.ContainerFromItem(ContactListBox.SelectedItem) as ListBoxItem;
if (listBoxItem == null)
{
return;
}
TextBlock txtBlock = FindVisualChildByName(listBoxItem, "ListTextBlock");
MessageBox.Show(txtBlock.Text);
}
private static T FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
string controlName = child.GetValue(NameProperty) as string;
if (controlName == name)
{
return child as T;
}
T result = FindVisualChildByName<T>(child, name);
if (result != null)
return result;
}
return null;
}
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lb = this.ContactsListBox.SelectedItem as ListBox;
this.Test_SomeOtherTextBlock.Text = lb.ToString();
}
will go something like this..
private void ContactsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox lb = this.ContactsListBox.SelectedItem as ListBox;
DataTemplate template=lb.ContentTemplate;
//Now here you have to extract the content of the data template
and then you need to extract the TextBlock from that content.
}
This is just an overview of the functionality.Sorry not able to post complete code.
I have a ListBox of Dockpanels which display "FieldName:, [_____] (user input textbox)". After the user populates the field, I'm looking for a LINQ way to take the pairs and throw them into a KeyValuePair object.
<DataTemplate x:Key="ExtraLoginInfoTemplate">
<DockPanel>
<TextBlock Name="CodeID" Text="{Binding Path=ID,Converter={BLL:CodeMarkupExtension}}" />
<TextBox Name="Input"/>
</DockPanel>
</DataTemplate>
<ListBox Name="extraLoginInfoListBox" ItemsSource="{Binding}" ItemTemplate="{StaticResource ExtraLoginInfoTemplate}"/>
//codebehind
extraLoginInfoListBox.DataContext = cvList; //list of codevalue objects
private void submitButton_click(object sender, RoutedEventArgs e)
{
KeyValuePair<string,string> myInputs = /* ? some linq query to get the data from extraLoginInfoListBox */
}
You need a property to be bound with your Input textbox to store whatever value was entered by user:
<TextBox Name="Input" Text="{Binding Path=IDValue, Mode=TwoWay}" />
And then, you can use following code:
var keyValuePairs = cvList.ToDictionary((obj) => obj.ID, (obj) => obj.IDValue);