How to determine the clicked item in a gridview - c#

I used this XAML code to create a gridview and add items to it:
<Grid x:Name="MainStack" HorizontalAlignment="Left" Height="628" Grid.Row="1" VerticalAlignment="Top" Width="1366">
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemsGridView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.RowSpan="2"
Padding="130,42,116,46"
ItemTemplate="{StaticResource Standard250x250ItemTemplate}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
Background="#FFFB0404" Margin="0,0,0,0" RenderTransformOrigin="0.489,0.503" ItemClick="MainPage_Click">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
<x:String>Item 4</x:String>
<x:String>Item 5</x:String>
<x:String>Item 6</x:String>
<x:String>Item 7</x:String>
<x:String>Item 8</x:String>
</GridView>
</Grid>
Then I tried using this C# code
private void MainPage_Click(object sender, ItemClickEventArgs e)
{
string output = e.ClickedItem.ToString();
int ClickValue = Convert.ToInt32(output);
if (ClickValue == 0)
{
this.Frame.Navigate(typeof(ItemsPageRSS));
}
}
to make the app navigate to a page when the 1st item is clicked but it gave an error.
Please if anyone can tell me how to isolate each iem and add a seperate click event for each and how to customize the gridview items by adding titles, subtitles and images to the items.
Thank you in advance.

Here I am giving you simple example if you can't understand MSDN sample. Just create new project and paste the whole code.
XAML
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<GridView
x:Name="itemGridView"
ItemTemplate="{StaticResource Standard250x250ItemTemplate}"
SelectionMode="None"
IsItemClickEnabled="True"
Background="#FFFB0404"
ItemClick="MainPage_Click"/>
</Grid>
C#
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var gvData = new ObservableCollection<MyData>();
for (int i = 0; i < 8; i++)
{
gvData.Add(new MyData
{
ID = i,
Image = new BitmapImage(new Uri("ms-appx:///Assets/Logo.png")), //You can add any image
Title = "Title " + i,
Subtitle = "Subtitle " + i
});
}
itemGridView.ItemsSource = gvData;
}
private void MainPage_Click(object sender, ItemClickEventArgs e)
{
MyData output = e.ClickedItem as MyData;
int ClickValue = output.ID;
if (ClickValue == 0)
{
this.Frame.Navigate(typeof(ItemsPageRSS));
//TODO : Do whatever you want
}
//.....
//TODO : Do operations for other items as well.
}
You may create MyData class outside the scope of MainPage (XAML Page) class.
public class MyData
{
public int ID { get; set; }
public ImageSource Image { get; set; }
public string Title { get; set; }
public string Subtitle { get; set; }
}

Related

UWP ListView's SelectedItem is reset when the ListView is in other ListView with large data

When large ListView's DataTemplate contains small ListView, small ListView's SelectedItem is reset.
I've made sample application which select each person's country from three choices.
I've selected "India" at last small ListView item(index:999) from code behind.
But when I scroll down, nothing is selected and the debug log is as below.
[Debug log]
Added: India, Removed:
Added:, Removed: India
[MainPage.xaml]
<ListView ItemsSource="{x:Bind People}" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Person">
<StackPanel BorderBrush="Black" BorderThickness="0,0,0,1">
<TextBlock Text="{x:Bind Country, Mode=OneWay}"/>
<ListView x:Name="CountryList"
ItemsSource="{x:Bind Countries, Mode=OneWay}"
SelectedItem="{x:Bind Country, Mode=TwoWay}"
SelectionChanged="CountryList_SelectionChanged">
</ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
[MainPage.xaml.cs]
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
GenerateSampleData();
}
private void GenerateSampleData()
{
for (int i = 0; i < 1000; i++)
{
People.Add(new Person
{
Countries = new List<string> { "China", "India", "USA" },
});
}
People[999].Country = "India";
}
private void CountryList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
StringBuilder sb = new StringBuilder("Added:");
foreach (var added in e.AddedItems)
{
if (added is string country)
{
sb.Append($" {country,-5}");
}
}
sb.Append(", Removed:");
foreach (var removed in e.RemovedItems)
{
if (removed is string country)
{
sb.Append($" {country,-5}");
}
}
Debug.WriteLine(sb);
}
Complete source is below.
https://github.com/tokane888/ListViewQuestion
And I'm not sure it relates but some small ListView is shown gray like below.
(I didn't touch this small ListView even from code behind or by hand.)
The reason your ListView item is not getting selected is that you are setting your property before the ListView is actually loaded. Better to set selected item in the ListView Loaded event.
You are seeing a gray area is because of the ListView virtualization as your ListView contains a large number of data.
In order to fix both the issue, please modify your code as below:
XAML:
<ListView ItemsSource="{x:Bind People}" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Person">
<StackPanel BorderBrush="Black" BorderThickness="0,0,0,1">
<TextBlock Text="{x:Bind Country, Mode=OneWay}"/>
<ListView x:Name="CountryList"
ItemsSource="{x:Bind Countries, Mode=OneWay}"
SelectedItem="{x:Bind Country, Mode=TwoWay}"
SelectionChanged="CountryList_SelectionChanged"
Loaded="CountryList_Loaded"
>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Code behind:
public sealed partial class MainPage : Page
{
public ObservableCollection<Person> People { get; } = new ObservableCollection<Person>();
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
GenerateSampleData();
}
private void GenerateSampleData()
{
for (int i = 0; i < 1000; i++)
{
People.Add(new Person
{
Countries = new List<string> { "China", "India", "USA" },
});
}
}
private void CountryList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
StringBuilder sb = new StringBuilder("Added:");
foreach (var added in e.AddedItems)
{
if (added is string country)
{
sb.Append($" {country,-5}");
}
}
sb.Append(", Removed:");
foreach (var removed in e.RemovedItems)
{
if (removed is string country)
{
sb.Append($" {country,-5}");
}
}
Debug.WriteLine(sb);
}
private void CountryList_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
People[999].Country = "India";
}
}
Also please refer to this post for detail insight.

Control inside datatemplate in ListBox UWP xaml

I have a ListBox consist of Datatemplate.
Here is my code:
<ListBox x:Name="MyListBox" SelectionChanged="MyListBox_SelectionChanged_1" SelectionMode="Single" IsItemClickEnabled="True">
<ListBox.ItemTemplate>
<DataTemplate>
<Rectangle Width="50" Height="45" Name="myRectangle" Fill="DodgerBlue" />
<Ellipse Grid.Column="0" Fill="LightGreen" Height="22" Width="22" />
<TextBlock Text="{Binding Initials}" x:Name="PersonInitials" />
<stackpanel>
<TextBlock TextWrapping="Wrap" x:Name="person_lbl" Text="{Binding SourceLink}" Foreground="DodgerBlue"/>
<TextBlock TextWrapping="Wrap" x:Name="detail_lbl" Text="{Binding ConversationId}" Foreground="DarkSlateGray"/>
</StackPanel>
<ToggleSwitch OffContent=" "/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Datatemplate consist of rectangle,Ellipse,3 textblocks and toggle switch which finally give an output like this as shown in image.
This is the template I will get.Please ignore the search bar.
Now Here is my Query:
I want to perform action on the basis of selection of a data_template in the listBox in which it should fetch the text of the textbox and display it somewhere.After searching about it on internet I have only found the examples like
<listbox>item1</listbox>
My ListBox does not consist of only one item it has many items that is making a template.
How can I fetch one textbox element on selection of whole template.Does anyone has idea how do so?
This is my code in c#:
class ReadJsonData
{
public List<Information> information { get; set; }
public ReadJsonData()
{
information = new List<Information>();
}
}
public class Information
{
public string SourceLink { get; set; }
public int ConversationId { get; set; }
public string Initials { get; set; }
}
and this is on MainPage.xaml
public MainPage()
{
this.InitializeComponent();
JsonReader();
}
public async void JsonReader()
{
Information infos = new Information();
infos.ConversationId = 1122;
infos.Initials = "LM";
infos.SourceLink = "abc";
Information info1 = new Information();
info1.ConversationId = 111;
info1.Initials = "MM";
info1.SourceLink = "pqr";
Information info2 = new Information();
info2.ConversationId = 1113;
info2.Initials = "NM";
info2.SourceLink = "vrl";
ReadJsonData rb = new ReadJsonData();
rb.information.Add(infos);
rb.information.Add(info1);
rb.information.Add(info2);
var rb1 = JsonConvert.SerializeObject(rb);
var rootobject = JsonConvert.DeserializeObject<ReadJsonData>(rb1);
foreach (var info in rootobject.information)
{
MyListBox.ItemsSource = rootobject.information;
}
private void MyListBox_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
var selectedItem = sender as Information;
string initials = selectedItem.Initials;
show_initial = initials;
}
}
Assuming you are setting the item source of the ListBox (MyListBox) to a list of items of your model class (List<SomeClassName>)..
If your model class is something like this :
public class SomeClassName
{
public string Initials { get; set; }
public string SourceLink { get; set; }
public string ConversationId { get; set; }
}
You can add this code to the OnSelectionChanged or Tapped event of your listbox to get the data members of the class:
private void MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selectedItem = sender as SomeClassName;
//Gives you the Initials of the selected list item
string intials = selectedItem.Initials;
}
Hope this helps..!
EDIT 1 :
First of all why are you iterating rootobject.information? you can simply use it as item source without the for loop..
foreach (var info in rootobject.information)
{
MyListBox.ItemsSource = rootobject.information;
}
Second, what does this line do ? show_initial = initials; is show_initial a variable ? what does it do ?
Edit 2 :
private void MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(MyListBox.SelectedItem != null)
{
var selectedItem = sender as Information;
//Gives you the Initials of the selected list item
string intials = selectedItem.Initials;
} else {
Debug.WriteLine("No item Selected");
}
}
Please check if the MyListBox.SelectedItem != null condition is satisfied or not.

Copy some text from ListView ItemTemplate to a string in UWP

I have this ListView in XAML:
<ListView x:Name="listView" Margin="10,72,10,120" Background="#7F000000" BorderBrush="#FF00AEFF" BorderThickness="1">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel BorderThickness="0,0,0,1">
<TextBlock Text="{Binding SSID}" Foreground="#FF067EB6" Margin="0,5,0,0"></TextBlock>
<TextBlock Text="{Binding BSSID}" Foreground="#FF067EB6"></TextBlock>
<TextBlock Text="{Binding NumOfBars}" Foreground="#FF067EB6"></TextBlock>
<TextBlock Text="{Binding WpsPin}" Foreground="#FF067EB6" Margin="0,0,0,5"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And something like this in the code behind:
class Networks
{
public string SSID { get; set; }
public string BSSID { get; set; }
public string NumOfBars { get; set; }
public string WpsPin { get; set; }
}
And this one to use the ListView:
listView.ItemsSource = null;
ObservableCollection<Networks> nets = new ObservableCollection<Networks>();
nets.Add(new Networks() { SSID = "SSID: " + networkSSID, BSSID = "BSSID: " + network.Bssid, NumOfBars = "Signal: " + network.SignalBars.ToString() + "/4", WpsPin = "WPS Pin: " + wpspin });
listView.ItemsSource = nets;
Now, I want to get the content of the selected item in the ItemSource and put it in a string. For example, I wanna get the "WpsPin" value of the selected item.
How can I do it?
You can subscribe to the ListView.SelectionChanged event and implement it in the code like the following:
XAML:
<ListView ... SelectionChanged="SelectionChanged">
C#:
private void SelectionChanged(object sender, SelectionChangedEventArgs e) {
Networks network = e.AddedItems.FirstOrDefault() as Networks;
if (network == null) return;
System.Diagnostics.Debug.WriteLine(network.WpsPin);
}

WPF Cascading Combobox to TextBox

I'm new to Programming and have some difficulties with cascading ComboBox to TextBox. Hire is my code:
MainWindow.xaml
Window x:Class="WpfApplication26.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="0,0,0,-1">
<ComboBox x:Name="Category" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" SelectionChanged="Category_SelectionChanged" Margin="309,52,0,0">
<ListBoxItem Name="clComboBoxItem1" Content="Comedy" Height="25"/>
<ListBoxItem Name="clComboBoxItem2" Content="Drama" Height="25"/>
<ListBoxItem Name="clComboBoxItem3" Content="Science Fisction" Height="25"/>
</ComboBox>
<ComboBox x:Name="Shows" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="309,79,0,0" SelectionChanged="Shows_SelectionChanged" />
<TextBox x:Name="TextBox1" HorizontalAlignment="Left" Height="23" Margin="309,106,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
</Grid>
MainWindow.xamlcs
namespace WpfApplication26
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Category_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Create List for Comedy selection
List<fruits> dropDownList_Comedy = new List<fruits>();
dropDownList_Comedy.Add(new fruits() { price = 10, Name = "Apples" });
dropDownList_Comedy.Add(new fruits() { price = 9, Name = "Bammamas" });
dropDownList_Comedy.Add(new fruits() { price = 1, Name = "Mango" });
//Create List for Drama selection
List<fruits> dropDownList_Drama = new List<fruits>();
dropDownList_Drama.Add(new fruits() { price = 10, Name = "Liver"});
//Create List for Science Fiction selection
List<fruits> dropDownList_SciFi = new List<fruits>();
dropDownList_SciFi.Add(new fruits() { price = 10, Name = "Apples2" });
//Check for SelectedIndex value and assign appropriate list to 2nd
if (Category.SelectedIndex == 0)
{
Shows.ItemsSource = dropDownList_Comedy;
Shows.DisplayMemberPath = "Name";
}
else if (Category.SelectedIndex == 1)
{
Shows.ItemsSource = dropDownList_Drama;
Shows.DisplayMemberPath = "Name";
}
else if (Category.SelectedIndex == 2)
{
Shows.ItemsSource = dropDownList_SciFi;
Shows.DisplayMemberPath = "Name";
}
{
}
}
private void Shows_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
{
fruits dropDownList_Comedy = Shows.SelectedItem as fruits ;
TextBox1.Text = Convert.ToString(dropDownList_Comedy.price);
}
{
fruits dropDownList_Drama = Shows.SelectedItem as fruits;
TextBox1.Text = Convert.ToString(dropDownList_Drama.price);
}
{
fruits dropDownList_SciFi = Shows.SelectedItem as fruits;
TextBox1.Text = Convert.ToString(dropDownList_SciFi.price);
}
}
}
}
Class1.cs
class fruits
{
public int price { get; set; }
public string Name { get; set; }
}
}
There is problem with System.NullReferenceException. I dont know what to do with it. Thanks for helping.
You're using SelectedValue instead of SelectedItem in your second block in the Shows_SelectionChanged function.
SelectedValue returns a String, which can't be parsed into a fruits (so it'll return null). And you're trying to access a member of null when using null.price, so it raises a NullReferenceException.
Edit
If you only want to display the SelectedItem of a ListBox in a TextBlock you can do:
<ListBox x:Name="MyListBox">
...
</ListBox>
<TextBox Text="{Binding ElementName=MyListBox,
Path=SelectedItem,
TargetNullValue=Nothing is selected,
Mode=OneWay}"/>
You don't need code behind in this case.

How to display images in ListView in Win8

The problem:
There is no images being displayed.Please help to correct my mistake. Thanks
1) I have stored the photo in a folder called Images and marked the photo as content
2) I have created a class and added it in the project
class ModelImage
{
public string Image_Name { get; set; }
public string Image { get; set; }
public string Description { get; set; }
}
3) I have added the ListView and a Button in MainPage
<ListView Name="LV" ItemsSource="{Binding}" HorizontalAlignment="Left" Height="552" Margin="693,27,0,0" Grid.Row="1" VerticalAlignment="Top" Width="582">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="30" Text="Hello">
<Image Source="{Binding Image}" Height="300" Width="300">
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
--- Button
private void Button_Click_1(object sender, RoutedEventArgs e)
{
List <ModelImage> list = new List <ModelImage>();
{
new ModelImage { Image_Name = "Meat", Image = "/Images/Meat_ProkChop.jpg", Description = "Pork Chop" };
new ModelImage { Image_Name = "Meat", Image = "/Images/Meat_Beef.jpg", Description = "Beef" };
};
LV.DataContext = list;
}
Do I need to use the hardcode Path for the photo inside the folder called Images?
Try "ms-appx:///Images/Image.jpg" instead of "/Images/Image.jpg". Getting the path right is important. Since it is default, this is likely correct already, but ensure your images are marked as "Content" in properties.
Best of luck!

Categories

Resources