Is there a way I can get the index of a tapped item in the AdaptiveGridView toolkit.
Heres my code:
Page Resources:
<Page.Resources>
<DataTemplate x:Key="Photos">
<Grid>
<Image Source="{Binding ImageURL}"
Stretch="UniformToFill"
HorizontalAlignment="Center"
VerticalAlignment="Center">
</Image>
<TextBlock Text="{Binding ImageText}"
FontSize="20">
</TextBlock>
</Grid>
</DataTemplate>
</Page.Resources>
XAML:
<UWPToolkit:AdaptiveGridView x:Name="AdaptiveGV" ItemHeight="200" ItemClick="AdaptiveGV_ItemClick" DesiredWidth="200" ItemTemplate="{StaticResource Photos}"/>
Code behind:
List<Images> ImageCollection = new List<Images>();
ImageCollection.Add(new Images()
{
ImageURL = Response[i].ProjectImageURL,
ImageText = Response[i].ProjectName
});
}
AdaptiveGV.ItemsSource = ImageCollection;
I want the get an index of the item i clicked. Is there a way to do that?
I want the get an index of the item i clicked. Is there a way to do that?
Yes you can, in the ItemClickEventArgs, you can get the clicked item and its index like this:
private void AdaptiveGV_ItemClick(object sender, ItemClickEventArgs e)
{
var item = e.ClickedItem as Images;
var index = ImageCollection.IndexOf(item);
}
Related
<GridView x:Name="MainGridStations" ItemsSource="{x:Bind Stations}" IsItemClickEnabled="True" ItemClick="GridView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:Station">
<Grid x:Name="WantToSelectByCode">
<Grid Background="White" HorizontalAlignment="Center" Width="300" Height="200" VerticalAlignment="Center">
<Grid Background="#e4f0fc" Height="65" VerticalAlignment="Bottom" Opacity="0.8">
<TextBlock x:Name="StationName" Text="{Binding Name}" FontWeight="Bold" Foreground="#2c9a8b" HorizontalAlignment="Center" />
</Grid>
</Grid>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
I'm trying to select a child by index of a dynamically filled gridview but what i've tried always returns null.
Like so for the first child for example:
var container = MainGridStations.ContainerFromIndex(0);
var presenter = VisualTreeHelper.GetChild(container, 0) as GridViewItem;
What am I doing wrong here?
You can get the corresponding GridViewItem from the method ItemsControl.ContainerFromIndex(Int32) directly and don't need to use the VisualTreeHelper to get it again.
var container = MainGridStations.ContainerFromIndex(0);
GridViewItem gridViewItem= container as GridViewItem;
gridViewItem.Background = new SolidColorBrush(Colors.Red);
The container have been the corresponding GridViewItem got from the index.
Note that: since your inner Grid have a Background="White" property configuration, you can delete the code to see the effect more obviously using my above code to change the gridViewItem.Background.
---Update---
You must get the GridViewItem after the items loaded. You can try the code in your GridView_ItemClick event handler or the page's loaded event hander. Also pay attention to my above note that to get more obvious effect, please delete the Background="White" in your above xaml code.
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var container = MainGridStations.ContainerFromIndex(0);
GridViewItem gridViewItem = container as GridViewItem;
gridViewItem.Background = new SolidColorBrush(Colors.Green);
}
//get the item here
private void GridView_ItemClick(object sender, ItemClickEventArgs e)
{
var container = MainGridStations.ContainerFromIndex(0);
GridViewItem gridViewItem= container as GridViewItem;
gridViewItem.Background = new SolidColorBrush(Colors.Red);
//var presenter = VisualTreeHelper.GetChild(container, 0) as GridViewItem;
}
I am having problem in affecting to a TextBlock "TxtChoisie" the Content (Nom/Categorie) of a ListViewItem in a universal app,this is my code:
xaml code:
<TextBlock Foreground="#575855" FontSize="18 " x:Name="TxtChoisie" />
<ListView x:Name="listme" IsItemClickEnabled="True" SelectionMode="Single" ItemClick="listme_ItemClick">
<ListViewItem>
<TextBlock Text="Nom" HorizontalAlignment="Center" Margin="0" Foreground="#727271" />
</ListViewItem>
<ListViewItem>
<TextBlock Text="Categorie" HorizontalAlignment="Center" Margin="0" Foreground="#727271" />
</ListViewItem>
</ListView>
code behind:
private void listme_ItemClick(object sender, ItemClickEventArgs e)
{
var myClickedItem = e.ClickedItem.ToString(); ;
TxtChoisie.Text = myClickedItem;
}
what I get in my TextBlock is not the Content(like Categorie or Nom)
thanks for Help
ClickedItem is an object. Source
You will need to convert it to a TextBlock and then read the Text property to get the right value:
var myClickedItem = ((TextBlock)e.ClickedItem).Text;
TxtChoisie.Text = myClickedItem;
You can miss this local variable out:
TxtChoisie.Text = ((TextBlock)e.ClickedItem).Text;
You should also check that the clicked item is a TextBlock before casting:
var myClickedItem = e.ClickedItem as TextBlock;
if (myClickedItem != null)
{
TxtChoisie.Text = myClickedItem.Text;
}
or in C# 6 syntax:
TxtChoisie.Text = myClickedItem?.Text;
I'm writing an app to play streaming music, In app I have many list (Ranking list, Search Result List, Highlight song list .....), Each list have a same datatemplate which I bind to a LongListSelector for each Page. So I use this datatemplate as resources and put it in app.xaml
<DataTemplate x:Key="BasicVideoTemplate">
<Grid Tap="ChangeSong_Tap" RowsAuto="50,50" ColumnsAuto="150,*" Background="White" Margin="5,0,5,10">
<Grid.ColumnDefinition>
<ColumnDefinition Width = "150"/>
<ColumnDefinition Width = "*"/>
</Grid.ColumnDefinition>
<Grid.RowDefinition>
<RowDefinition Height = "50"/>
<RowDefinition Height = "50"/>
</Grid.RowDefinition>
<Border BorderThickness="1" BorderBrush="Black" Grid.RowSpan="2" Grid.Column="0" VerticalAlignment="Center" Margin="5,0,5,0">
<Image Source="{Binding Cover}"/>
</Border>
<TextBlock Text="{Binding Name}" Grid.Row="0" Grid.Column="1" Style="{StaticResource BlackTextBlock}" Margin="5,0,0,0"/>
<TextBlock Text="{Binding Artist}" Grid.Row="1" Grid.Column="1" Foreground="Black" Margin="5,0,0,0"/>
<!-- .............. -->
</Grid>
</DataTemplate>
And this code (which i put in app.xaml.cs) to select a song from list, create a AudioTrack from this item and navigate to playSongPage:
private void ChangeSong_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var item = (SongItemModel)(sender as FrameworkElement).DataContext;
App.Model.ChangeSong(item.Id); /// this code will create a audio track for this item
(Application.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri("/Pages/DetailSongPage.xaml", UriKind.Relative));
}
Problem here is, I have to create a List< AudioTrack> for my playlist , So how can I get the parent list of clicked item and add it to the List< AudioTrack> , while all this code was put in app.xaml.cs ???
I would handle it in the SelectionChanged event of each longlistselector instead. The whole Tap thing on the grid doesn't sit well with me.
<phone:LongListSelector x:Name="myLSS" SelectionChanged="myLSS_SelectionChanged"/>
// event handler changes to
private void myLSS_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
LongListSelector lls = sender as LongListSelector; // get lls
var item = (SongItemModel) lls.SelectedItem;
App.Model.ChangeSong(item.Id); /// this code will create a audio track for this item
// now your ObservableCollection is just the ItemsSource, save a reference to it
// in the State manager so you can reference it on another page if you wish
ObservableCollection<SongItemModel> obs = (ObservableCollection<SongItemModel>) lls.ItemsSource;
PhoneApplicationService.Current.State["current_obs"] = obs;
// navigate..............
(Application.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri("/Pages/DetailSongPage.xaml", UriKind.Relative));
}
PROBLEM:
I got the answer when doing some binding from ListBoxSource to ListBoxDisplay BUT weird thing happened:
The selecting and deselecting of items are working fine and displays exactly the selected items on the other ListBox named "ListBoxDetails BUT everytime I select an item the image is gone but selection highlights remain but has no more image in it. (You can still deselect it though even if no more image because the screenspace is still there)
NOTE: I have no other control inside the ListBoxSource (SelectionMode=Multiple) ONLY Image
CODE XAML:
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<WrapPanel Height="149" Orientation="Horizontal" Width="193">
<Image HorizontalAlignment="Left" Height="128" Width="180" Margin="0"/>
</WrapPanel>
</DataTemplate>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate2">
<UniformGrid x:Name="UniformGridImageList"/>
</ItemsPanelTemplate>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<ListBox x:Name="ListBoxSource" Width="450" Margin="9,3,442,178" ItemsPanel="{DynamicResource ItemsPanelTemplate2}" SelectionMode="Multiple" d:LayoutOverrides="GridBox" HorizontalAlignment="Left" />
<ListBox Name="ListBoxDisplay" Height="659" HorizontalAlignment="Right" Margin="460,5,0,0" VerticalAlignment="Top" Width="382" ItemsSource="{Binding ElementName=ListBoxSource, Path=SelectedItems}" />
<Button x:Name="buttonLoadImages" Content="Button" HorizontalAlignment="Left" Height="51" Margin="33,0,0,70" VerticalAlignment="Bottom" Width="183" Style="{DynamicResource ButtonStyle1}" Click="buttonLoadImages_Click"/>
<Button Content="Clear" Height="55" HorizontalAlignment="Right" Margin="0,717,442,0" Name="buttonClearListBox" VerticalAlignment="Top" Width="177" Click="button1_Click" />
</Grid>
CODE C#:
above declaration:
private List<Image> _imageList = new List<Image>();
.
.
.
private void buttonLoadImages_Click(object sender, System.Windows.RoutedEventArgs e)
{
this._imageList = GetImageList(#"C:\Users\Public\Pictures\Sample Pictures");
foreach (Image curImage in this._imageList)
{
ListBoxSource.Items.Add(curImage);
}
}
#region GetImageList Method
private List<Image> GetImageList(string strPath)
{
List<Image> imageList = new List<Image>();
string strFilePath = "";
if (Directory.Exists(strPath) == false)
{
MessageBox.Show(string.Format("{0} path could not be found.", strPath));
return imageList;
}
try
{
DirectoryInfo dirInfo = new DirectoryInfo(strPath);
FileInfo[] files = dirInfo.GetFiles("*.jpg",SearchOption.AllDirectories);
foreach (FileInfo curFile in files)
{
strFilePath = curFile.FullName;
Image curImage = new Image();
BitmapImage bmpImage = new BitmapImage();
bmpImage.BeginInit();
bmpImage.UriSource = new Uri(curFile.FullName, UriKind.Absolute);
bmpImage.EndInit();
curImage.Height = 140;
curImage.Stretch = Stretch.Fill;
curImage.Source = bmpImage;
curImage.Margin = new Thickness(10);
imageList.Add(curImage);
}
if (imageList.Count == 0)
MessageBox.Show(string.Format("No image files could be found in {0}", strPath));
}
catch (Exception ex)
{
MessageBox.Show(string.Format("{0}-{1}", ex.Message, strFilePath));
}
return imageList;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
this.listBoxSource.Items.Clear();
}
You are creating Image UI objects and adding them directly to your ListBox.
This means that the SelectedItems is an Image UI object, so ListBox #2 is trying to set it's Items to the exact same Image object reference. This isn't allowed in WPF because UI objects can only have a single parent, however because it is a Binding error, WPF is silent about it (except for probably a warning)
I would recommend making your List<Image> into a List<string> which contains the path name for the image, and changing your <Image> in the template to use that string as it's Source. Also, don't forget to set the ItemTemplate on both your ListBoxes.
<DataTemplate x:Key="ItemTemplate">
<WrapPanel Height="149" Orientation="Horizontal" Width="193">
<Image Source="{Binding }" HorizontalAlignment="Left" Height="128" Width="180" Margin="0" />
</WrapPanel>
</DataTemplate>
I did a quick test and it works fine once you fill your ListBoxes with Strings instead of UI objects
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.