Xamarin Forms listitem (on)hold gesture - xamarin.forms

I have a listview with labels and entries. I want a gesture or somthing that when I long press a label it wil show an alert display with the name of the label. So far I have only when you press once, need the same but then when you press longer.
My code of the listview
var listView = new ListView();
var productDataTemplate = new DataTemplate(() =>
{
var grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(2, GridUnitType.Star)
});
var typeLabel = new Label { FontAttributes = FontAttributes.Bold,
BackgroundColor = Color.White};
typeLabel.SetBinding(Label.TextProperty, "Type");
var entry = new Entry
{
TextColor = Color.Black,
BackgroundColor = Color.White
};
entry.SetBinding(Entry.TextProperty, "Quantity");
grid.Children.Add(typeLabel,0,0);
grid.Children.Add(entry,1,0);
grid.BackgroundColor = Color.Black;
return new ViewCell { View = grid };
});
listView.ItemTemplate = productDataTemplate;
listView.ItemsSource = products;
listView.ItemSelected += (sender, e) => {
DisplayAlert("item tapped", e.SelectedItem.ToString(), "ok");
};
wrapLayout.Children.Add(listView);

AFAIK Xamarin.forms by default supports Tap, Pinch & Pan gesture. So to do long press you need to handle with the CustomRenderer for each supported platforms or you can make use of XForms lab which by default supports most of the gestures which includes Long Press. Hope that helps!

Related

Xamarin Forms ListView does not Fire TapGestureOrganizer in Android, OK in UWP

I have a simple listview in my Xamarin Forms App:
lstMetrics = new ListView();
DataTemplate dataTemplate = new DataTemplate(() =>
{
Label lblMetricDesc = new Label();
lblMetricDesc.FontSize = PublicConstants.SmallFontSize;
lblMetricDesc.Margin = 5;
lblMetricDesc.SetBinding(Label.TextProperty, "Description");
return new ViewCell { View = lblMetricDesc };
});
TapGestureRecognizer listViewTap = new TapGestureRecognizer();
listViewTap.NumberOfTapsRequired = 2;
listViewTap.Tapped += ListViewTap_Tapped;
lstMetrics.ItemTemplate = dataTemplate;
lstMetrics.WidthRequest = 100;
lstMetrics.HeightRequest = 250;
lstMetrics.GestureRecognizers.Add(listViewTap);
This works fine in UWP but it does not fire in Android Environment. Is there a workaround for this in Android?
Any and all help will be appreciated.

Xamarin.forms - BoxView in Customized ViewCell

I want to set VisibleProperty of BoxView as false for the last element of list which is defined in a viewcell containing stacklayout (grid+boxview). Is there any way to make it false so that last element wont contain boxview separator line?
Solution:
You can add a bool property isShow to your viewModel and use this property to control whether the boxView is visible or not.
public class MyViewModel
{
//use this property to control whether the boxView is visible
public bool isShow { get; set; }
}
And then binding this property to the boxView in your customCell By boxOne.SetBinding(BoxView.IsVisibleProperty, new Binding("isShow")):
public CustomCell()
{
//instantiate each of our views
var grid = new Grid();
var horizontalLayout = grid;
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
var boxOne = new BoxView { BackgroundColor = Color.Purple };
var boxTwo = new BoxView { BackgroundColor = Color.AliceBlue };
grid.Children.Add(boxOne, 0, 0);
grid.Children.Add(boxTwo, 1, 1);
//Binding here
boxOne.SetBinding(BoxView.IsVisibleProperty, new Binding("isShow"));
View = horizontalLayout;
}
At last , when you creating a new instance of MyViewModel, you can set the isShow property true/false to control whether the boxView is visible in your cell.
public MainViewCode()
{
myCollection = new ObservableCollection<MyViewModel>();
ListView lstView = new ListView();
lstView.ItemTemplate = new DataTemplate(typeof(CustomCell));
myCollection.Add(new MyViewModel { isShow = true });
myCollection.Add(new MyViewModel { isShow = false });
lstView.ItemsSource = myCollection;
Content = lstView;
}

How to find whether Listview scrolled up or down in xamarin forms?

I need to hide some view, when listview scrolled up and display that view again, when list view scrolled down.
I used
private void ScheduleServiceList_ItemAppearing(object sender, Xamarin.Forms.ItemVisibilityEventArgs e)
{
var currentItem = e.Item as VehicleService;
double listviewheight = ScheduleServiceListView.Height;
if (viewModel.VehicleServiceList[0].Id == currentItem.Id)
{
SearchEntryLayout.IsVisible = true;
HeadingGrid.Margin = new Thickness(0, -70, 0, 0);
}
}
What about:
var listView = new ListView(ListViewCachingStrategy.RecycleElement)
{
....
ItemTemplate = new DataTemplate(() =>
{
return new MyListViewCellView(new List<int> { ... /* ids to disable or other objects */ });
})
};

xamarin binding a button in code to viewModel (without xaml)

I'm using the mvvm approach to develop a barcode scanning app with xamarin. The main hurdle was that the 3rd party scanner object does not work in xaml. I used a ContentPage to create a simple logic-less c# code view which allows me to have a footer with buttons and a logo overlayed at the bottom of the scanner. My problem is that could not find any great best practices for binding items from your code view to your viewModel, as opposed binding a xaml view to a viewModel. Here is some of my view below.
public class BarcodeScannerPage : ContentPage
{
ZXingScannerView zxing;
BarcodeViewModel viewModel;
public BarcodeScannerPage() : base()
{
try
{
viewModel = new BarcodeViewModel();
BindingContext = viewModel;
zxing = new ZXingScannerView
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Options = new MobileBarcodeScanningOptions
{
TryHarder = true,
DelayBetweenContinuousScans = 3000
},
ScanResultCommand = viewModel.GetResult
};
var cancelButton = new Button
{
BackgroundColor = Color.Gray,
Text = "Cancel",
TextColor = Color.Blue,
FontSize = 15,
Command = viewModel.CancelButton
};
Binding cancelBinding = new Binding
{
Source = viewModel.CancelIsAvailable,
//Path = "ShowCancel",
Mode = BindingMode.OneWay,
};
cancelButton.SetBinding(IsVisibleProperty, cancelBinding);
var doneButton = new Button
{
BackgroundColor = Color.Gray,
Text = "Done",
TextColor = Color.Blue,
FontSize = 15,
Command = viewModel.DoneButton
};
Binding doneBinding = new Binding
{
Source = viewModel.DoneIsAvailable,
//Path = "ShowDone",
Mode = BindingMode.OneWay,
};
doneButton.SetBinding(Button.IsVisibleProperty, doneBinding);
When a barcode is scanned my command, GetResultCommand, sends the result to my BarcodeView model. I have created two Bools in my BarcodeView model named isDoneAvailable and isCancelAvailable. I want to bind these values to the Visibility property of the doneButton and cancelButton in my view. Right now the buttons are bound to whatever the bool values are at the creation of BarcodeViewModel, but they DO NOT update. I need to be able to control visibility from the GetResultCommand method of my BarcodeViewModel. Specifically, when a certain number of barcodes are scanned, I want to make the buttons appear and disappear. I have a feeling they don't update because the path is not set, but when I uncomment the path, the binding doesn't work at all. Any ideas what I've done wrong with the bindings of the buttons, or the correct way to set the Path to my bools in the viewModel? Here is some of my BarcodeViewModel code below.
public class BarcodeViewModel : INotifyPropertyChanged
{
public bool CancelIsAvailable { get { return _cancelIsAvailable; } set { _cancelIsAvailable = value; OnPropertyChanged("ShowCancel"); } }
public bool DoneIsAvailable { get { return _doneIsAvailable; } set { _doneIsAvailable = value; OnPropertyChanged("ShowDone"); } }
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
I still would like to know the correct way to get this binding to update but, I was able to work-around this issue by creating a button in my viewModel and referencing it in my view. Then when I dynamically updated the button in my viewModel, it also updated in my view.

Xamarin Forms - How To Use A ListVIew

I am trying to populate a listview with a customcell I made. I know how to do it with a tableview, but i have no idea how to do it with a listview. Can someone explain to me please, thank you
Excuse the very rough snippet of code but it is merely to explain the concept behind listviews and databinding.
In my example below I create a listview, assign a custom viewCell and bind the view cell to a model. The model data is populated by XML data retrieved from the server(Code emitted for simplicity). Simpler implementations can be done should you require a listview with hardcoded data.
I suggest reading through the http://developer.xamarin.com/guides/cross-platform/xamarin-forms/introduction-to-xamarin-forms/ and researching the MVVM principle
Additionally the best example code I have found to go through is an enlightening application written by James Montemagno https://github.com/jamesmontemagno/Hanselman.Forms
public TestPage()
{
private ListView listView; // Create a private property with the Type of Listview named listview
listView = new ListView(); //Instantiate the listview
var viewTemplate = new DataTemplate(typeof(CustomViewCell)); //Create a variable for the custom data template
listView.ItemTemplate = viewTemplate; // set the data template to the variable created above
this.Content = new StackLayout()
{
Children = {
listView
}
};
}
Custom View Cell:
public class CustomViewCell : ViewCell
{
public CustomViewCell()
{
Label Test = new Label()
{
Font = Font.BoldSystemFontOfSize(17),
TextColor = Helpers.Color.AppGreen.ToFormsColor(),
BackgroundColor = Color.White
};
var image = new Image();
image.Source = ImageSource.FromFile("testing.png");
Label Test2 = new Label();
tour_Desc.SetBinding(Label.TextProperty, "Test");
round_Desc.SetBinding(Label.TextProperty, "Test2");
var grid = new Grid
{
VerticalOptions = LayoutOptions.FillAndExpand,
RowDefinitions =
{
new RowDefinition {Height = GridLength.Auto },
new RowDefinition {Height = GridLength.Auto },
new RowDefinition {Height = 1}
},
ColumnDefinitions =
{
new ColumnDefinition {Width = GridLength.Auto},
new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)},
new ColumnDefinition {Width = 80 }
}
,BackgroundColor = Color.White,
};
grid.Children.Add(image, 0, 0);
Grid.SetRowSpan(image, 2);
grid.Children.Add(tour_Desc, 1, 0);
Grid.SetColumnSpan(tour_Desc, 2);
grid.Children.Add(Test, 1, 1);
grid.Children.Add(Test2, 1, 2);
this.View = grid;
}
}
View Model:
public partial class GamesResult
{
public string Test { get; set; }
public string Test1 { get; set; }
}

Resources