developing a picker that pops out from the selected frame downward in xamarin forms - xamarin

I have a design i'm trying to implement. Although I've ben working with Rg.plugin for a while trying out different animations and entry behaviour but it's always covering the whole screen.
However, the current design I'm working with is different.
here is the image
Please does anyone have an idea how I can achieve this using xamarin forms please.
Any help will be appreciated.
Note, I already have the design in place using pancakeView and Rg.plugin to pop it out on click. However, the positioning is what I haven't been able to achieve. though I've not written any code for it yet cos I prefer to do my research right.
Please I need anyone to point me to the right path or how to achieve this.
thanks in advance

According to your screenshot, you can do custom control using entry and ListView to get it, there is also one custom control that you can take a look:
Installing Xamarin.Forms.EntryAutoComplete
Uisng this custom control like:
<ContentPage
x:Class="demo3.listviewsample.Page36"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:customControl="clr-namespace:EntryAutoComplete;assembly=EntryAutoComplete">
<ContentPage.Content>
<StackLayout>
<customControl:EntryAutoComplete
ItemsSource="{Binding Countries}"
MaximumVisibleElements="5"
Placeholder="Enter country..."
SearchMode="{Binding SearchMode}"
SearchText="{Binding SearchCountry}"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
public class dialogvidemodel:ViewModelBase
{
private string _searchCountry = string.Empty;
private SearchMode _searchMode = SearchMode.Contains;
public string SearchCountry
{
get => _searchCountry;
set
{
_searchCountry = value;
RaisePropertyChanged("SearchCountry");
}
}
public List<string> Countries { get; } = new List<string>
{
"African Union",
"Andorra",
"Armenia",
"Austria",
"Togo",
"Turkey",
"Ukraine",
"USA",
"Wales"
};
public SearchMode SearchMode
{
get => _searchMode;
set
{
_searchMode = value;
RaisePropertyChanged("SearchMode");
}
}
}
More detailed info, please take a look:
https://github.com/krzysztofstepnikowski/Xamarin.Forms.EntryAutoComplete

Related

After installing FFImageLoading images don't show at all

My Xamarin Forms 5 app will allow users to upload their own images which can be large. I noticed that large images were taking a long time to show so I installed FFImageLoading and followed the instructions on their Github page at https://github.com/luberda-molinet/FFImageLoading/wiki/Xamarin.Forms-API.
Specifically, I installed the following packages:
Xamarin.FFImageLoading Version="2.4.11.982"
Xamarin.FFImageLoading.Forms Version="2.4.11.982"
Xamarin.FFImageLoading.Svg.Forms Version="2.4.11.982"
Xamarin.FFImageLoading.Transformations Version="2.4.11.982"
I also initialized it as follows:
Under Android, in OnCreate method of MainActivity.cs, I added FFImageLoading.Forms.Platform.CachedImageRenderer.Init(enableFastRenderer:true); AND FFImageLoading.Forms.Platform.CachedImageRenderer.InitImageViewHandler();
Under iOS, in FinishedLaunching() method of AppDelegate.cs, I added FFImageLoading.Forms.Platform.CachedImageRenderer.Init(); AND FFImageLoading.Forms.Platform.CachedImageRenderer.InitImageSourceHandler();
I first tried it without changing anything in my XAML files, meaning I used the regular Image control and images would NOT show at all.
I then tried the following and I see NOTHING at all:
...
xmlns:ffil="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
...
<ffil:CachedImage
Source="{Binding FileUrl}"
DownsampleWidth="150"
DownsampleToViewSize="True"/>
IMPORTANT:
I also want to mention that the images are displayed within CollectionView controls AND in all cases, their source is a URL and NOT a local path.
Any idea what maybe the issue here and how to fix it?
As I'm aware FFImageLoading is not maintained anymore. A lot of apps are still using the package but keep in mind that reported open issues will most likely not be fixed. It is sad because this is one of the most popular packages for Xamarin Forms, but it looks like we will have to start looking for alternatives.
Good luck with this.
I checked your steps that you followed the instructions.Obviously,your steps are correct and I manage to display the image{using URL} with CollectionView as you said,hope it can give you some insights.
Model:
MyModel.cs
public class MyModel
{
public int id { get; set; }
public string FileUrl { get; set; }
}
View:
MainPage.xaml
<CollectionView ItemsSource="{Binding MyModels}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="2" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<ContentView Padding="0">
<ffil:CachedImage
Source="{Binding FileUrl}"
DownsampleWidth="150"
DownsampleToViewSize="True"/>
</ContentView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Bind the ViewModel in backend:
BindingContext = new MainPageViewModel();
ViewModel:
MainPageViewModel.cs
public class MainPageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<MyModel> myModels;
public ObservableCollection<MyModel> MyModels
{
get { return myModels; }
set { myModels = value; }
}
public MainPageViewModel()
{
MyModels = new ObservableCollection<MyModel>
{
new MyModel{id = 1, FileUrl = "http://loremflickr.com/600/600/nature?filename=simple.jpg"},
new MyModel{id = 2, FileUrl ="http://loremflickr.com/600/600/nature?filename=simple.jpg"},
new MyModel{id = 3, FileUrl = "http://loremflickr.com/600/600/nature?filename=simple.jpg"},
new MyModel{id = 4, FileUrl ="http://loremflickr.com/600/600/nature?filename=simple.jpg"},
new MyModel{id = 5, FileUrl = "http://loremflickr.com/600/600/nature?filename=simple.jpg"},
new MyModel{id = 6, FileUrl ="http://loremflickr.com/600/600/nature?filename=simple.jpg"}
};
}
}
Update:
In Android, it works well.However,in iOS there's already a reported issue:
github.com/luberda-molinet/FFImageLoading/issues/1498

What is the property in control to be set to get the value from AppResult.Text in Xamarin.UITest?

I am trying to create custom control in Xamarin.Forms which has the unique id for automation. So, i have set the android renderer's contentDescription property. So, i can get the AppResult.Label property to identify the control. But, my requirements is that how to get the control's text property? What property i have to set in control level with the corresponding text to get it in AppResult.Text property.
[Test]
[Description("SampleTest")]
public void WelcomeTextIsDisplayed()
{
App.Repl();
AppResult[] results = App.WaitForElement("myControl");
Assert.IsTrue(results[0].Text == "My Control Text", results[0].Text + "\n" + results[0].Description + "\n" + results[0].Id + "\n" + results[0].Label);
}
For more information, I have prepared the simple example to explain better about my case. Here, i have derived my custom control from Grid and i introduced the Text property. When i try to view the element using Repl() method, it does not show the Text property but it shows the text properties for Label & Entry controls.
<StackLayout >
<Label Text="Hello, Custom Renderer!" />
<local:MyEntry Text="In Shared Code" AutomationId="myEntry" />
<local1:CustomView Text="Sample" BackgroundColor="Red" HeightRequest="500" AutomationId="customControl" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"/>
</StackLayout>
public class CustomView : Grid
{
public CustomView()
{
}
public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(string),string.Empty);
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
Result while calling App.Repl() ,
I'm not sure how different Xamarin.Forms are to Xamarin.Android (which is mostly what my experience is in.)
What happens if you try
app.Query(c => c.Id("NoResourceEntry-2").Property("Text")).SingleOrDefault();
or some variation of the above? Can you then do something with this? I Hope this helps or points you in the right direction.
Try to use with index position like this:
app.Query(c=>c.Id("NoResourceEntry-2"))[0].Text
similarly you can use class for same:
app.Query(c=>c.Class("LabelRenderer"))[0].Text
Query for Class("LabelRenderer") gave 2 results. So in above example, you can see it gave you 2 results but you have to use index for particular result.

In a Xamarin MVVM application, how can I change what I see on the screen from the ViewModel?

My application viewModel responds to a user clicking a button to see test results:
private void AddDetailRows(List<QuizHistory> quizHistoryList)
{
quizDetails.Children.Clear();
quizDetails.Children.Add(AddData(quizHistoryList));
quizDetails.Children.Add(new LineTemplate());
}
Where quizDetails is the name of an element in the view.
But this doesn't work for me as the view model doesn't know what the view looks like and does not have access to the names of elements.
In a MVVM application, how is this problem solved?
You are completely right, that is not something that ViewModel is responsible of.
So, whatever you want to do with UI is not responsibility of the ViewModel.
If this is really the only option, then you can think of creating boolean properties in your VM and binding them to your views and then changing that boolean from false to true or vice versa on button click command which is binded to your VM.
To simplify it:
MyView.xaml
<StackLayout>
<Button Command="{Binding ShowHideQuizHistoryCommand}" ... />
<StackLayout x:Name="QuizHistory"
IsVisible={Binding ShowQuizHistory }>
//
</StackLayout>
</StackLayout>
MyViewModel.cs
private bool _showQuizHistory ;
public bool ShowQuizHistory
{
get { return _showQuizHistory ; }
set
{
_showQuizHistory = value;
OnPropertyChanged();
}
}
public ICommand ShowHideQuizHistoryCommand => new Command(() =>
{
ShowQuizHistory = !ShowQuizHistory;
});
So, this is just an example based on what you provided in question.
You can also use visual states, converters, triggers and behaviors in order to achieve this, but in my opinion this is the easiest way.

Xamarin Forms ListView not Updating from ObservableCollection

The ListView of my XAML file is being filled with a ViewModel that has an ObservableCollection from a service but the ListView is not showing the information. I already check that the service is returning the correct information.
This is the code of my XML file :
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XAMLUnit1.Views.NetflixRoulettePage" Title="Movie">
<ContentPage.Content>
<StackLayout>
<AbsoluteLayout>
<BoxView Color="Gray" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1"></BoxView>
<SearchBar x:Name="searchBar"
Placeholder="Search By Actor's name"
PlaceholderColor="White"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.1,0.1,1,1" SearchCommand="{Binding SearchMovieCommand}" ></SearchBar>
</AbsoluteLayout>
<ListView x:Name="ListOfMovies"
ItemsSource="{ Binding MovieList}" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<ImageCell
ImageSource="{Binding poster_path, StringFormat='https://image.tmdb.org/t/p/w500{0}'}">
</ImageCell>
<StackLayout Orientation="Horizontal">
<TextCell Detail="{Binding title}"></TextCell>
<TextCell Detail="{Binding release_date}"></TextCell>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
This is the ViewModel that calls the service and it's uses its ObservableCollection as ItemsSource for the ListView :
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using XAMLUnit1.Models;
using XAMLUnit1.ServiceImpl;
using XAMLUnit1.Services;
namespace XAMLUnit1.ViewModels
{
public class MovieRouletteViewModel
{
IMovieService service;
public ObservableCollection<Movie> MovieList { get; set; }
public ICommand SearchMovieCommand { get; set; }
public MovieRouletteViewModel()
{
service = new MovieServiceFinder();
SearchMovieCommand = new Command(GetMovies);
}
private void GetMovies()
{ var list= service.GetMovies("");
MovieList = list;
}
}
}
public partial class NetflixRoulettePage : ContentPage
{
MovieRouletteViewModel viewModel;
public NetflixRoulettePage()
{
InitializeComponent();
viewModel = new MovieRouletteViewModel();
BindingContext = viewModel;
}
private void SearchBar_TextChanged(object sender, TextChangedEventArgs e)
{
}
}
Do not set the ObservableCollection to a new List it will break the binding. Clear the items from the list and add the new items to it.
public MovieRouletteViewModel()
{
service = new MovieServiceFinder();
SearchMovieCommand = new Command(GetMovies);
MovieList = new ObservableCollection<Movie>();
}
private void GetMovies()
{
var list= service.GetMovies("");
MovieList.Clear();
foreach(Movie movie in list)
{
MovieList.Add(movie);
}
}
There is a few things i want to note on this problem, though mainly as the comments rightly illuminate, replacing the collection with a new collection breaks the bindings. hence why its not updating.
However there are several solutions to consider.
Implement INotifyPropertyChanged on the collection and replace the whole collection like you are doing, This will work fine. However it does resets the scroll and basically recalculates everything from scratch. Some would say this defeats the point of an ObservableCollection as they have their own built in notification plumbing, Yeah it does. Though, if you are replacing the whole Collection with a new collection then you are going to save on oodles of Cyclic calculations when compared to cleaRing and adding each item back individually Which will basically fire for every update
Call Clear and Add on each item individually.. If the collection hasn't changed much, you can even take it a step further by just comparing the 2 collections and updating whats needed. However once again, if the collections are dissimilar, then this approach is still expensive, and on a mobile device you want to minimize screen recalculations where ever possible .
Create a subclassed collection, implement your own replace/update, and Add/Remove range methods, and INotifyPropertyChanged giving you the best of both worlds, this will allow atomic modification of the collection and then you can fire property changed event once.
There are many examples of all these approaches online, its just worth noting clearing and adding items sometimes is not the best approach for mobile devices. It depends how big your collections are, how much is changing and why.
If it is a completely different list, then replacing the collection is fine in my opinion.
If its the same list, then well you may want to compare and modify to save on property changes
Anyway good luck
I disagree with other answers. You can set the Movies as many times as you want, this is not the problem.
The problem is just that your viewmodel doesn't implement INotifyPropertyChanged.
Your UI is just not notified when you set your ObservableCollection.
Your service command is actually replacing the ObservableCollection, you need to change your GetMovies() method to
var list = service.GetMovies("");
MovieList.clear();
foreach(Movie m in list)
{ MovieList.Add(m);}

Data binding property not working

first of all sorry for my english.
I am developing a WP7 app, and I still haven't completely understood the data binding structure. I have a page that has some data obtained through data binding. Data is generated within the .cs, and it works fine.
But on another page I have some data that is obtained from data binding too, but I want it to come from a UI input text instead. It's simple, just a textbox and a textblock, so the user writes something on the textbox and so it shows up on the textblock that's on the same page. But it's not working, the textblock remains empty.
It's something like this:
<TextBox Name="TestInput">
<TextBlock Text="{Binding TestText}">
Above is what's on the XAML.
public partial class NewItem : PhoneApplicationPage
{
public String TestText { get; set; }
public NewItem()
{
InitializeComponent();
TestText = "TestInput.Text";
}
}
And this above is what's on the C#.
BUT!! It doesn't end here. Since the textblock wasn't showing anything, I ended desperately trying to assign some plain String to the TestText property. Like this:
TestText = "HELLO WORLD";
But when the app starts and the page loads, the textblock shows nothing. I just don't understand what am I missing, or doing wrong.
I will appreciate if someone could clear me up the databinding structure, or at least explain me what did I do wrong so I can figure it out myself.
Thanks in advance guys!
You have to assign the DataContext before you want the binding effect.So whenever there is a change in the text box, you write the code in the textchanged event.
this.DataContext=TestText
And one more change that you need to perform is that you are not actually setting the property.It should be like
TestText=TestInput.Text
for your understanding of binding i am putting a simple working example..just follow this..
this is you page on which you bind the data of textbox to someproperty textboxText..when you finished writing in this textbox.then all the writtentext automatically come ino this property. and this property is also binded to textbloack so when your textbloack got focus it will got to the get of the property and automatically fill it.
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Orientation="Horizontal" >
<TextBox x:Name="testTextbox" Height="50" Width="200" Text="{Binding TextboxText,Mode=TwoWay}" />
<TextBlock x:Name="testTextblock" Height="50" Width="1000" Text="{Binding TextboxText,Mode=OneWay}" Foreground="White" />
</StackPanel>
</Grid>
this is your page.cs class in which i have also shown you how to implement inotifyproperty changed..it will help you in future..
public sealed partial class MainPage : Page,INotifyPropertyChanged
{
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
}
private string _TextboxText;
public string TextboxText
{
get
{
return _TextboxText;
}
set
{
_TextboxText = value;
FirePropertyChanged("TextboxText");
testTextblock.UpdateLayout();
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
public event PropertyChangedEventHandler PropertyChanged;
protected void FirePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

Resources