Searchbar for datagrid - xamarin

im trying to keep a searchbar for datagrid,so when the user enters certain value in search bar,the datagrid should show only entered value.i installed xamarin.forms.xamarin.i have gone through different example but no luck i did get what iam looking for.Looking forward for positive responce.
Thank you

This can be achieved by putting a SearchBar above a ListView. Binding the Text value of the SearchBar to a property in your ViewModel enables you to handle changes to the Text property by querying the data.
In XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<SearchBar Grid.Row="0" Text="{Binding Filter}" HeightRequest="40" />
<ListView Grid.Row="1" ItemsSource="{Binding Items}" />
</Grid>
In the ViewModel:
public List<MyObject> Items { get; set; }
public string Filter
{
get { return filter; }
set
{
filter = value;
// Apply filter to list of Items here...
}
}

Related

Change item control property of checked listview item Xamarin.Forms

Hy,
I am trying to show a comment input if the item checkbox is checked and hide it else, i have this XAML
<ListView ItemsSource="{Binding TaskItems}" x:Name="TasksItems" HasUnevenRows="True" VerticalScrollBarVisibility="Default" SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout IsVisible="True" Orientation="Vertical">
<Grid BackgroundColor="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<StackLayout Grid.Column="0" Grid.Row="0">
<input:CheckBox Type="Box" IsChecked="{Binding TaskChecked , Mode=TwoWay}"/>
</StackLayout>
<StackLayout Grid.Column="0" Grid.Row="1" IsVisible="{Binding CommentRequired}">
<Entry BackgroundColor="White" PlaceholderColor="Black" HeightRequest="40" TextColor="Black"/>
</StackLayout>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
and i have this c# code to read the items from database
public class TaskData
{
public bool TaskChecked { get; set; }
public bool CommentRequired { get; set; }
}
public partial class HomePage : ContentPage
{
public HomePage()
{
ObservableCollection<TaskData> TaskItems { get; set; }
ObservableCollection<TaskData> TasksList;
TaskItems = new ObservableCollection<TaskData>();
//Loop the tasks from database result
While...
TaskItems.Add(new TaskData
{
TaskChecked = false,
CommentRequired = false,
});
//End Loop
TasksListView.ItemsSource = TaskItems;
}
}
Now i need to add a "CheckChanged" event to show the comment Entry (IsVisible="True") when the user check the checkbox of the targed listview item
Thanks
First add the event.
<input:CheckBox Type="Box" IsChecked="{Binding TaskChecked , Mode=TwoWay}" CheckedChanged="OnCheckBoxCheckedChanged"/>
Add Name for the second stack
<StackLayout x:Name="StackLayoutEntry" Grid.Column="0" Grid.Row="1" IsVisible="{Binding CommentRequired}">
<Entry BackgroundColor="White" PlaceholderColor="Black" HeightRequest="40" TextColor="Black"/>
</StackLayout>
Then in code Behind use this function to find the entry for the clicked checkbox
void OnCheckBoxCheckedChanged(object sender, CheckedChangedEventArgs e)
{
var Sender = (CheckBox)sender;
var stacklayoutentry = Sender.Parent.FindByName<StackLayout>("StackLayoutEntry");
stacklayoutentry.IsVisible = True;
}
This might also help you also Check
Another approach but you an identifier to your selected item.
Check

FindByName control inside another control on ContentPage in Xamarin

I want to set focus on SearchBar when he appears. The problem is that SearchBar is placed inside of popup view and I need to access him from ViewModel.
In standard way I would use
Xamarin.Forms.SearchBar tmp_SearchBar = this.Page.FindByName("fro_SearchBar_NewItem") as Xamarin.Forms.SearchBar;
but that's not working anymore.
Here is XAML
<sfPopup:SfPopupLayout x:Name="fro_Popup_NewItem" Opened="fro_Popup_NewItem_Opened" Grid.Row="1" HorizontalOptions="Center" VerticalOptions="Center" BackgroundColor="Black">
<sfPopup:SfPopupLayout.PopupView>
<sfPopup:PopupView BackgroundColor="Black" WidthRequest ="400" HeightRequest ="100" ShowFooter="False" ShowHeader="False">
<sfPopup:PopupView.ContentTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!--Search bar-->
<Grid Grid.Row="0" HorizontalOptions="Center" VerticalOptions="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<SearchBar x:Name="fro_SearchBar_NewItem"
Grid.Column="0"
Text="{Binding SearchText_Popup, Mode=TwoWay}"
SearchCommand="{Binding SearchCommand}"
Placeholder="Find"
CancelButtonColor="White"
TextColor="White"
PlaceholderColor="Gray"/>
</Grid>
</Grid>
</DataTemplate>
</sfPopup:PopupView.ContentTemplate>
</sfPopup:PopupView>
</sfPopup:SfPopupLayout.PopupView>
</sfPopup:SfPopupLayout>
Nested FindByName doesn't work either.
Syncfusion.XForms.PopupLayout.SfPopupLayout tmp_Popup = _Page.FindByName("fro_Popup_NewItem") as Syncfusion.XForms.PopupLayout.SfPopupLayout;
Xamarin.Forms.SearchBar tmp_SearchBar = tmp_Popup.FindByName("fro_SearchBar_NewItem") as Xamarin.Forms.SearchBar;
Thanks
You can use Task to open a new thread to complete this operation in code-behind.
Xaml:
<SearchBar x:Name="fro_SearchBar_NewItem" Placeholder="...." BackgroundColor="White"/>
Code behind:
public partial class PagePop : Popup
{
public PagePop()
{
InitializeComponent();
Task.Run(() => myTask());//Create and start the thread
}
private void myTask()
{
Thread.Sleep(300);
fro_SearchBar_NewItem.Focus();
}
}
It seems that this wasn't so far from right direction, neither of the comments actually.
Syncfusion.XForms.PopupLayout.SfPopupLayout tmp_Popup = _Page.FindByName("fro_Popup_NewItem") as Syncfusion.XForms.PopupLayout.SfPopupLayout;
Xamarin.Forms.SearchBar tmp_SearchBar = tmp_Popup.FindByName("fro_SearchBar_NewItem") as Xamarin.Forms.SearchBar;
but I found the one which works and I don't have to create separate XAML for Popup.
private void fro_Popup_NewItem_Opened(object sender, EventArgs e)
{
try
{
var nativeObject = (object)fro_Popup_NewItem.GetType().GetRuntimeProperties().FirstOrDefault(x => x.Name.Equals("NativeObject")).GetValue(fro_Popup_NewItem);
var formsPopupviewContentTemplate = nativeObject.GetType().GetRuntimeFields().FirstOrDefault(x => x.Name.Equals("formsPopupViewContentTemplate")).GetValue(nativeObject);
var SearchBar = (formsPopupviewContentTemplate as Grid).FindByName<SearchBar>("fro_SearchBar_NewItem");
SearchBar?.Focus();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Thanks for help, everyone.

Xamarin.Forms: Detect last item in a BindableLayout

I'm using a bindable layout to display a list of items. The items are bound to an ObservableRangeCollection of key-value pairs
public ObservableRangeCollection<KeyValuePair<string, string>> Items { get; set; }
This is the layout that renders the Items -- each one of the rows are separated by a line using BoxView:
<StackLayout BackgroundColor="Transparent" BindableLayout.ItemsSource="{Binding Items}" Padding="20">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="1" />
</Grid.RowDefinitions>
<Label Grid.Column="0"
Grid.Row="0"
Text="{Binding Key}"/>
<Label Grid.Column="1"
Grid.Row="0"
HorizontalOptions="End"
HorizontalTextAlignment="End"
Text="{Binding Value}"/>
<BoxView Grid.Column="0"
Grid.Row="1"
Grid.ColumnSpan="2"
HeightRequest="1" />
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
The issue is there is an extra line at the end of the list which I wish to hide after rendering the last element in the observable collection.
I would need to figure out if the last item is being rendered on the BindableLayout and set the IsVisible property of the BoxView to false but I'm not sure how to do this using XAML.
One approach is to define a class with a boolean property, that you set on each item to true or false. This controls whether that BoxView appears.
MyItem.cs:
public class MyItem
{
public string Key { get; set; }
public string Value { get; set; }
/// <summary>
/// Default to "true". Most items will show the line.
/// </summary>
public bool ShowLineUnder { get; set; } = true;
MyModelView.cs:
public class MyModelView
{
public ObservableCollection<MyItem> Items { get; set; }
public MyModelView()
{
Items.Add(new MyItem(...));
Items.Add(new MyItem(...));
Items.Add(new MyItem(...));
// Hide line on last item.
Items[Items.Count - 1].ShowLineUnder = false;
}
}
in XAML of ItemTemplate:
<BoxView ... IsVisible="{Binding ShowLineUnder}" />
Adapt as needed.
Another approach would be to consider that each member of the BindingLayout is an entry in the layout's Children collection. With this knowledge, you would only need to hide the BoxView on the last child in the Children collection.
var layout = [reference to the StackLayout];
layout.Children.Last().IsVisible = false; // add using for System.Linq
Besides hiding the BoxView with the IsVisible property, you can also hide it by getting a reference to the grid ColumnDefinition and setting the Width to 0. This can be useful when there is more than one control to hide.

Entry FindByName getting always null in xamarin forms mvvm

I have a button
and i want to focus an entry on button click
so my button command is:
public Command FocusPassword
{
get
{
return new Command(() =>
{
Entry myEntry= Application.Current.MainPage.FindByName<Entry>("pEntry");
passwordEntry.Focus();
});
}
}
myEntry always returning null,so how to solve this?
I simply solve this:
Page currentPage = Navigation.NavigationStack.LastOrDefault();
Entry passwordEntry = currentPage.FindByName<Entry>("PassEntry");
passwordEntry.Focus();
Is it myEntry that is null, or passwordEntry? You are assigning the returned object to myEntry but then trying to set the focus on passwordEntry:
Entry myEntry= Application.Current.MainPage.FindByName<Entry>("pEntry");
passwordEntry.Focus();
And yes, make sure that the Entry does have the x:Name set to pEntry, e.g.:
<Entry x:Name="pEntry" ... />
You could try to use my demo as well.
MainPage.xaml (Do not forget to BindingContext)
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:EntryDemo"
x:Class="EntryDemo.MainPage">
<StackLayout>
<Grid Margin="10">
<Grid.BindingContext>
<local:BindingViewModel/>
</Grid.BindingContext>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Entry
Grid.Row="0"
HorizontalOptions="CenterAndExpand"
Text="account"
x:Name="accountEntry"
/>
<Entry
Text="password"
Grid.Row="1"
HorizontalOptions="CenterAndExpand"
x:Name="pEntry"
/>
<Button
Grid.Row="2"
HorizontalOptions="CenterAndExpand"
x:Name="MyButton"
Text="FocusEntry "
Command="{Binding FocusCommand}"
/>
</Grid>
</StackLayout>
</ContentPage>
You should run FindByName in execute method
BindingViewModel.cs
public class BindingViewModel: BindableObject
{
public BindingViewModel()
{
FocusCommand = new Command(
execute: () =>
{
Entry accountEntry = Application.Current.MainPage.FindByName<Entry>("accountEntry");
Entry myEntry = Application.Current.MainPage.FindByName<Entry>("pEntry");
accountEntry.Focus();
}
);
}
public ICommand FocusCommand { private set; get; }
}

How to hide a Grid row and ListView column so that no empty space is visible?

I have two issues with Xamarin Grid and ListView.
(1) In ListView, I have seven columns. Based on a condition, the fifth and sixth columns need to be hidden in such a way that there is no blank space visible after forth column. I tried to set IsVisble=false but it shows blank space in between.
(2) Similar issue is with Grid. Inside a ContentView, I have Grid with ten rows. Based on certain condition, I want to hide rows seven and eight in such a way that the empty portion should get collapsed. User should not be able to view the empty row.
If from code-behind I try removing rows using the below code, I suspect the .XAML may crash as row numbers need to be reordered.
GridView gv = listview.View as GridView;
GridViewColumn cd = gv.Columns[0];
gv.Columns.Remove(cd);
gv.Columns.Add(cd);
For the grid problem, just be sure to use Binding to set the RowHeight dynamically.
So as soon as you want to hide those rows, you set the height to 0.
Code would look like this:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Test"
x:Class="Test.MainPage">
<StackLayout Margin="0,20,0,0">
<Grid RowSpacing="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="{Binding RowHeight}" />
<RowDefinition Height="{Binding RowHeight}" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Label Text="Row 1" Grid.Row="0" HorizontalTextAlignment="Center" />
<Label Text="Row 2" Grid.Row="1" HorizontalTextAlignment="Center" />
<Label Text="Row 3" Grid.Row="2" HorizontalTextAlignment="Center" />
<Label Text="Row 4" Grid.Row="3" HorizontalTextAlignment="Center" />
<Label Text="Row 5" Grid.Row="4" HorizontalTextAlignment="Center" />
</Grid>
<Button Text="Hide rows" Clicked="OnClicked" />
</StackLayout>
</ContentPage>
public partial class MainPage : ContentPage, INotifyPropertyChanged
{
private int _rowHeight = 50;
public int RowHeight
{
get => _rowHeight;
set
{
_rowHeight = value;
OnPropertyChanged();
}
}
public MainPage()
{
InitializeComponent();
BindingContext = this;
}
private void OnClicked(object sender, System.EventArgs e)
{
RowHeight = 0;
}
}
You can set the row Height to Auto and then bind the IsVisible property of the content you want to hide.

Resources