Cannot capture listview itemselected - xamarin

I'm trying to capture the item clicked on in a listview. Everything I've seen here deals with Xamarin Forms, I am NOT using Xamarin Forms. I build my listview and display it fine, but I cannot figure out how to capture the item click. My build code:
ListView PhoneNumberList;
PhoneNumberList = FindViewById<ListView>(Resource.Id.listViewNumbers);
ListOfPhoneNumbers = new List<string>();
if (PhoneNumberData.Tables[0].Rows.Count > 0)
{
foreach (DataRow MyDataRow in PhoneNumberData.Tables[0].Rows)
{
ListOfPhoneNumbers.Add(MyDataRow["FirstName"].ToString() + " " + MyDataRow["LastName"].ToString() + " " + MyDataRow["PhoneNumber"].ToString());
}
}
else
{
ListOfPhoneNumbers.Add("Currently there are no phone numbers available in this list
}
ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItemMultipleChoice, ListOfPhoneNumbers);
PhoneNumberList.Adapter = adapter;
This code displays the name and phone number as intended, but I cannot figure out how to detect when the Listview is clicked. I tried:
PhoneNumberList.ItemSelected += (sender, args) =>
{
var Sel = PhoneNumberList.SelectedItem;
};
But it never gets called on the click. I've also tried:
PhoneNumberList.ItemSelected += delegate (object sender, AdapterView.ItemSelectedEventArgs args) { PhoneNumberList_ItemSelected(); };
PhoneNumberList_ItemSelected never gets called either.
My Listview XML:
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="148.4dp"
android:id="#+id/listViewNumbers" />
So what am I doing wrong?

Ok, after slogging around the internet for a few hours, I was able to work it out. It was rather simple and I had already discovered the answer, I just formated one statement wrong and it sent me on a wild goose chase to find the answer. My updated code:
ListView PhoneNumberList;
PhoneNumberList = FindViewById<ListView>(Resource.Id.listViewNumbers);
ListOfPhoneNumbers = new List<string>();
if (PhoneNumberData.Tables[0].Rows.Count > 0)
{
foreach (DataRow MyDataRow in PhoneNumberData.Tables[0].Rows)
{
ListOfPhoneNumbers.Add(MyDataRow["FirstName"].ToString() + " " + MyDataRow["LastName"].ToString() + " " + MyDataRow["PhoneNumber"].ToString());
}
}
else
{
ListOfPhoneNumbers.Add("Currently there are no phone numbers available in this list
}
ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItemMultipleChoice, ListOfPhoneNumbers);
PhoneNumberList.Adapter = adapter;
Exactly the same, now I add the one line of code I just couldn't get right (duh):
PhoneNumberList.ItemClick += PhoneNumberList_ItemClick;
Originally I had used PhoneNumberList.ItemClick += PhoneNumberList_ItemClick(); and the error it generated sent me off on that aforementioned wild goose chase and there went several hours of my life I'll never get back, lol. The PhoneNumberList_ItemClick code:
void PhoneNumberList_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
// We now can write code here to set the checkbox in the listview to checked
// All I got to do now is figure out how to do THAT. Stay tuned ....
}
So, hopefully this will save someone the ordeal I put myself through.
**** Update ****
Didn't take long to figure out how to set the item clicked's checkbok, changes to PhoneNumberList_ItemClick code below:
void PhoneNumberList_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
ListView MyListView = (ListView)sender;
if (MyListView.IsItemChecked(e.Position))
{
MyListView.SetItemChecked(e.Position, true);
}
else
{
MyListView.SetItemChecked(e.Position, false);
}
}
.... And that's all folks ....

Related

Simple example only works correctly first time, Why?

This is a simplified snippet of a larger WPF project to illustrate the problem.
When the play button is pressed, this code plays the mp3's "1, 2, 3, 4, 5" then stops.
When the play button is pressed, the dispatch timer starts. On every Tick, the Metronome_Run event is called. The Metronome_Run event assigns a mp3 to play by indexing an array.
The problem is, it works fine the first time you press play, you get 1,2,3,4,5, but when pressing play again, you get 2,4,5, then pressing play again, you get 3,5! As if the indexing of the files seems to be offset each time play is pressed somehow.
When stepping through with the debugger, it runs perfect every time, yet without any breakpoints set, (like in the build), it works correctly only the first time and does not work correctly on further play button presses.
Any help is appreciated!
public partial class MainWindow : Window
{
private MediaPlayer mediaPlayer = new MediaPlayer();
List<int> NoteValArray = new List<int>() { 1,2,3,4,5 };
private DispatcherTimer timer1;
int numVal = 0;
int numIndex = 0;
private float tempo = 35f;
public MainWindow()
{
InitializeComponent();
timer1 = new DispatcherTimer();
}
private void Metronome_Run(object sender, EventArgs e)
{
if (NoteValArray.Count > numIndex) // if we are not outside the list bounds
{
numVal = NoteValArray[numIndex]; // get the value at this list index and place it in numVal
numIndex ++; // increment
}
else { timer1.Stop(); return; }
// Load the mp3 indicated by numVal
if (numVal == 1) { mediaPlayer.Open(new Uri("1.mp3", UriKind.Relative)); }
else if (numVal == 2) { mediaPlayer.Open(new Uri("2.mp3", UriKind.Relative)); }
else if (numVal == 3) { mediaPlayer.Open(new Uri("3.mp3", UriKind.Relative)); }
else if (numVal == 4) { mediaPlayer.Open(new Uri("4.mp3", UriKind.Relative)); }
else if (numVal == 5) { mediaPlayer.Open(new Uri("5.mp3", UriKind.Relative)); }
mediaPlayer.Play(); // play whats loaded
}
private void Start_Button_Click(object sender, RoutedEventArgs e)
{
numIndex = 0;
timer1.Tick += Metronome_Run; // run this at each tick
timer1.Interval = TimeSpan.FromMilliseconds(10000 / (tempo / 6));
timer1.Start();
}
}
}
Solved!
I moved "timer1 = new DispatcherTimer();" from the mainwindow function, and placed it in the "Start_Button_Click" event with the other timer code.
My guess is I was starting more than 1 timer with each play press, and that was causing the bug. Thanks to all who took time to look at my problem.

Xamarin - How to know what has been clicked in collection view?

I have a CollectionView with an image and a button in it. I use following code to see if somebody pressed anywhere within the cell:
private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (((CollectionView)sender).SelectedItem != null)
{
var item = (picdata)e.CurrentSelection.FirstOrDefault();
((CollectionView)sender).SelectedItem = null;
if (allowfullscreen == "1" || allowfullscreen == "true")
{
Navigation.PushAsync(new Picture());
}
}
}
But how can I know if he clicked the button inside the cell? I was trying to do it via the Click event, but then I do not know which one of all the buttons has been clicked.
you can get the item from the BindingContext of the sender
var item = (picdata)(Button)sender.BindingContext;

WPF Using of Frame

While I'm using frame in Mainwindow , initially i hide an item in Mainwindows.
When i pressed a button in frame Page1 , I want to make item in mainwindow as visible.But i can't do it.I tried to updatelayout() , refresh() functions but anything is changed.Anyone has a knowledge about this??
This code is in MainWindow
private void Window_Loaded(object sender, RoutedEventArgs e)
{
müsteributton.IsEnabled = false;
string yer = "Pages/kullanicigiris.xaml";
frame1.Source = new Uri(yer, UriKind.Relative);
frame1.Margin = new Thickness(-175, 0, 0, 0);
}
This code is in kullanicigiris page
private void Dispatcher_Tick(object sender, EventArgs e)
{
i++;
if (i == 2)
{
dispatcher.Stop();
frm1 = new MainWindow();
frm1.frame1 = null;
DependencyObject currParent = VisualTreeHelper.GetParent(this);
while (currParent != null && frm1.frame1 == null)
{
frm1.frame1 = currParent as Frame;
currParent = VisualTreeHelper.GetParent(currParent);
}
// Change the page of the frame.
if (frm1.frame1 != null)
{
frm1.frame1.Source = new Uri("Window1.xaml", UriKind.Relative);
frm1.müsteributton.IsEnabled = true;
}
}
}
Thanks.
You can define a DependencyProperty in the MainWindows.
<TextBlock x:Name="textBlock" Height="399" TextWrapping="Wrap" Text="Show/ Hide" VerticalAlignment="Top" Visibility="{Binding SetVisibility, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
public static readonly DependencyProperty SetVisibilityProperty =
DependencyProperty.Register("SetVisibility", typeof(Visibility), typeof(Mainfreampage), new
PropertyMetadata(Visibility.Visible, null));
public Visibility SetVisibility
{
get { return (Visibility)GetValue(SetVisibilityProperty); }
set { SetValue(SetVisibilityProperty, value); }
}
In your page click event, you can use the following code find the MainWindows and change the DependencyProperty value.
var mw = Application.Current.Windows
.Cast<Mainfreampage>()
.FirstOrDefault(window => window is Mainfreampage) as Mainfreampage;
mw.SetVisibility = Visibility.Hidden;
Your bug is here:
frm1 = new MainWindow();
You are creating a brand new window, and then making your changes in that window.
But: that's not the window the user's looking at!
Taking the approach you've embarked on, your frame code needs to keep track of the Window object it's actually being hosted in, and then use that reference for dealing with the update.
That said, that entire approach is flawed. The navigation should be modeled in a view model data structure, activated via an ICommand object, and optionally via timer (as you seem to be doing here). Frame source and button state can be manipulated through bindings to properties in your view model data structure.
But, at the end of the day, the code you've got should work fine, once you start using the correct Window object.

Win10 App - Holding & Releasing the map to manipulate an element on the interface

I working on an UWP (Win10) App with a simple location picker function. The user can drag the map on the wanted location. A basic Pushpin thats always in the center of the Map window acts as the location indicator. It works just like the free location pick in WhatsApp.
To give the user feedback that he is moving the center pin, I want to raise the pin when the user is moving the map and lower it again on release.
Here the simple code to raise the pin (and manipulate the shadow):
private void MyMap_MapHolding(MapControl sender, MapInputEventArgs args)
{
iconSwitch = true;
if(iconSwitch == true) {
centerPin.Margin = new Thickness(0, 0, 0, 60);
centerPinShadow.Opacity = 0.3;
centerPinShadow.Width = 25;
}
But this event doesn't seem to be affected on click & hold or tap & hold. Am I missing something?
FYI: I tried this out with the MyMap_MapTapped(...) method, and it worked just fine, but I need it when the map is dragged not just tapped.
Chees!
I've tested and debugged, MapHolding event can't work by me either. For your purpose, CenterChangedLink event maybe helpful, I've tested it too.
Here is part of my sample code:
RandomAccessStreamReference mapIconStreamReference;
public Maptest()
{
this.InitializeComponent();
myMap.Loaded += MyMap_Loaded;
myMap.MapTapped += MyMap_MapTapped;
myMap.MapHolding += MyMap_MapHolding;
myMap.CenterChanged += MyMap_CenterChanged;
mapIconStreamReference = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/MapPin.png"));
}
private void MyMap_Loaded(object sender, RoutedEventArgs e)
{
myMap.Center =
new Geopoint(new BasicGeoposition()
{
//Geopoint for Seattle
Latitude = 47.604,
Longitude = -122.329
});
myMap.ZoomLevel = 12;
}
private void MyMap_MapTapped(Windows.UI.Xaml.Controls.Maps.MapControl sender, Windows.UI.Xaml.Controls.Maps.MapInputEventArgs args)
{
var tappedGeoPosition = args.Location.Position;
string status = "MapTapped at \nLatitude:" + tappedGeoPosition.Latitude + "\nLongitude: " + tappedGeoPosition.Longitude;
rootPage.NotifyUser( status, NotifyType.StatusMessage);
}
private void MyMap_MapHolding(Windows.UI.Xaml.Controls.Maps.MapControl sender, Windows.UI.Xaml.Controls.Maps.MapInputEventArgs args)
{
var holdingGeoPosition = args.Location.Position;
string status = "MapHolding at \nLatitude:" + holdingGeoPosition.Latitude + "\nLongitude: " + holdingGeoPosition.Longitude;
rootPage.NotifyUser(status, NotifyType.StatusMessage);
}
private void MyMap_CenterChanged(Windows.UI.Xaml.Controls.Maps.MapControl sender, object obj)
{
MapIcon mapIcon = new MapIcon();
mapIcon.Location = myMap.Center;
mapIcon.NormalizedAnchorPoint = new Point(0.5, 1.0);
mapIcon.Title = "Here";
mapIcon.Image = mapIconStreamReference;
mapIcon.ZIndex = 0;
myMap.MapElements.Add(mapIcon);
}
At first I thought, even when the MapHoling event can't work, the Tapped action before holding should handled by MapTapped event, but it is seems this action is ignored. So remember, if a user hold the Map but not move it, nothing will happen.

How to stop pivot looping

I want to create a wizard control from the pivot control. To achieve this I need to stop the pivot looping. I want to stop the pivot control moving forward from the last item to the first and backwards from the first to the last.
I'm pretty sure I should be able to intercept the manipulations e.g. cancel if I detect a right to left manipulation on the last pivot item. I can capture this in ManipulationDelta but don't know how to cancel the manipulation.
I have tried setting e.Handled = True but it didn't work.
I tried to set IsHitTestVisisble to false but this kills all manipulations. I tried setting it back to true in ManipulationCompleted but this then allows all manipulations.
Any ideas?
Cheers
Steve
The pivot is not designed to be used as a wizard and does not support stopping it's looping behaviour as this would create an inconsistent UX for users.
If you really must create a wizard do it with multiple pages.
Don't use a Pivot for a Wizard. Create your own transitions instead.
I couldn't reply to your comment on Matts answer but I just wanted to point you to this:
http://forty3degrees.wordpress.com/2011/07/19/creating-a-swipable-contentcontrol/
It's the last entry in my very neglected blog and should provide a good base for creating a wizard using a pivot style swipe.
Calum.
EDIT: I tried to do what you wanted with the pivot but couldn't find a way to stop it looping. The only way that I can think of to achieve this would be to derive a custom control from Pivot. Unfortunately SelectedIndex/SelectedItem are not virtual so you would need to hide them (with the new modifier) and reproduce the logic from the base class.
It's just an alternative solution I've posted here - you can try to make use of XNA framework TouchPanel and Touch.FrameReported Event:
using Microsoft.Xna.Framework.Input;
public MainPage()
{
InitializeComponent();
myPivot.IsHitTestVisible = false; // disable your Pivot
Touch.FrameReported += Touch_FrameReported;
TouchPanel.EnabledGestures = GestureType.HorizontalDrag;
}
TouchPoint first;
private void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
TouchPoint mainTouch = e.GetPrimaryTouchPoint(this);
if (mainTouch.Action == TouchAction.Down)
first = mainTouch;
else if (mainTouch.Action == TouchAction.Up && TouchPanel.IsGestureAvailable)
{
if (mainTouch.Position.X < first.Position.X)
{
if (myPivot.SelectedIndex < myPivot.Items.Count - 1)
myPivot.SelectedIndex++;
}
else if (mainTouch.Position.X > first.Position.X)
{
if (myPivot.SelectedIndex > 0)
myPivot.SelectedIndex--;
}
}
}
Thought it would probably work from WP7.1 as TouchPanel is available from that version of the OS.
If you absolutely want to keep the Pivot from looping, here is a quick and dirty hack:
int previousSelectedIndex = 0;
public PageWithPivot()
{
InitializeComponent();
pivot.SelectionChanged += new SelectionChangedEventHandler(pivot_SelectionChanged);
}
private void pivot_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (pivot.SelectedIndex == 0 && previousSelectedIndex == <number Of screens - 1>)
pivot.SelectedIndex = <number Of screens - 1>;
previousSelectedIndex = pivot.SelectedIndex;
}
This causes your PivotControl to jump back to the last pivotItem. Not very pretty but works.
This is so weird because it only works in the Emulator. I guess you shan't mess with the UI
You can use MVVM:
<phone:Pivot Foreground="Black"
Name="pivot1"
Title="AIDE"
SelectedIndex="{Binding SelectedItem, Mode=TwoWay}">
Cs:
private class HelpViewModel : ViewModelBase
{
public HelpViewModel()
{
}
private int _SelectedItem = 0;
public int SelectedItem
{
get
{
return _SelectedItem;
}
set
{
if (_SelectedItem != value)
{
if (value == 3)
_SelectedItem = 0;
else
_SelectedItem = value;
RaisePropertyChanged(() => SelectedItem);
}
}
}
}
public AppHelpPivot()
{
InitializeComponent();
LayoutRoot.DataContext = new HelpViewModel();
}

Resources