Ive created a picker with data inside, when selected the data is added to a list. I want to the values that are added to the list to follow to the next page when calculate button is pressed.. tried a few different approaches but i cant get it right..
.cs
// add from picker to listview function
ObservableCollection<LayersClass> listProducts = new ObservableCollection<LayersClass>();
private void MainPicker_SelectedIndexChanged(object sender, EventArgs e)
{
// feedback popup box
var product = MainPicker.Items[MainPicker.SelectedIndex];
DisplayAlert(product, "Layer added to calculation list", "OK");
// if selected add to list
if (null != product)
{
LayersClass layer = new LayersClass();
layer.Product = product;
listProducts.Add(layer);
}
}
//calculate button
private async void Button_Clicked(object sender, EventArgs e)
{
// send selected values to CalculationPage ??
await Navigation.PushAsync(new CalculationPage());
}
xaml:
<ListView
x:Name="productsListView"
HasUnevenRows="False"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
BackgroundColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="MenuItem_Clicked" Text="Delete" IsDestructive="true" CommandParameter="{Binding .}" />
</ViewCell.ContextActions>
<StackLayout>
<Label Text="{Binding Product}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Margin="0,0,0,90" Text="Calculate" Clicked="Button_Clicked" FontSize="Medium" TextColor="#00AB8E" HorizontalOptions="Center" BackgroundColor="Transparent"/>
You should use parameter to pass data to the another page.
private async void Button_Clicked(object sender, EventArgs e)
{
// send selected values to CalculationPage ??
//Also you should write there an event.
var item = sender as Button;
var selectedItem = item as LayersClass;
await Navigation.PushAsync(new CalculationPage(item));
}
public CalculationPage(string item){
//when you type here dot after typing item like this -> item. you can see the layerclass items.
}
Related
I have a Picker in Xamarin and I want to pass the selected item in Picker to the another page(TablePage). Below this Picker there is a button and whenever it is clicked I want to go to the other page and display the selected value in the pther page.
<Picker x:Name="SelectTablePicker" Title="Select table" TextColor="#676FA3" TitleColor="#676FA3" FontSize="Title" ItemsSource="{Binding TablesFromViewModelCollector}" ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding SelectedTable}" />
<Button x:Name="SelectTableButton" Text="Select Table" HorizontalOptions="Center" Style="{DynamicResource TitleStyle}" Clicked="Selected_Button" />
So how I am trying to pass this value is with click event:
async void Selected_Button(object sender, System.EventArgs e)
{
var SelectTablePicker = (Picker)sender;
int selectedIndex = SelectTablePicker.SelectedIndex;
if (selectedIndex != -1)
{
await Navigation.PushAsync(new TablePage((string)SelectTablePicker.ItemsSource[selectedIndex]));
}
}
And on the Table Page, I created Label where I want to show the selected item:
<Label x:Name="MyLabel" Text="#" HorizontalOptions="Fill" Grid.Column="0" BackgroundColor="#FF5959" TextColor="#EEF2FF" HorizontalTextAlignment="Left" Padding="0, 0, 0, 10" VerticalTextAlignment="Center"/>
And here its controller:
public TablePage(string tableName)
{
InitializeComponent();
MyLabel.Text = $"{UserName}";
}
But whenever I click the button I am getting an error and I couldnt figure out why.
this is a button click event, so the sender is a Button, not a Picker
var SelectTablePicker = (Picker)sender;
int selectedIndex = SelectTablePicker.SelectedIndex;
instead just do this
// SelectTablePicker is the name of your picker
int selectedIndex = SelectTablePicker.SelectedIndex;
and even better, you are already binding SelectedItem="{Binding SelectedTable}" so you could just get the value of SelectedTable directly from your VM
finally, you want to cast the selected item as a Table, not a string
new TablePage((Table)SelectTablePicker.ItemsSource[selectedIndex])
I have a list of CartUsers. I execute the command remove item from the list. I managed to remove each item in the list. However how does the list Preferences update.
My code:
cart.xaml
<StackLayout Padding="15,13" BindableLayout.ItemsSource="{Binding CartUsers}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout Margin="0,2.5" x:DataType="model:CartUser">
<Label Text="{Binding NumberProduct}" />
<ImageButton x:Name="removeitem" Clicked="removeitem_Clicked" >
<ImageButton.Source>
<FontImageSource Color="red" Size="10" FontFamily="FontAwesome" Glyph="{x:Static local:FontAwesomeClass.TrashAlt}"/>
</ImageButton.Source>
</ImageButton>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
2.cart.xaml.cs
CartUserViewModel cartUserViewModel;
private void removeitem_Clicked(object sender, EventArgs e)
{
var mycart = Preferences.Get("CartUser", "defaultcart");
var getcart = JsonConvert.DeserializeObject<List<CartUser>>(mycart);
var button = sender as ImageButton;
var itemcart = button.BindingContext as CartUser;
cartUserViewModel.RemoveItemCart.Execute(itemcart);
//Preferences.Set("CartUser", JsonConvert.SerializeObject(getcart));
}
Update...
private void removeitem_Clicked(object sender, EventArgs e)
{
var mycart = Preferences.Get("CartUser", "defaultcart");
var getcart = JsonConvert.DeserializeObject<List<CartUser>>(mycart);
var button = sender as ImageButton;
var itemcart = button.BindingContext as CartUser;
cartUserViewModel.RemoveItemCart.Execute(itemcart);
getcart.Remove(itemcart);
int count = getcart.Count();
Preferences.Set("CartUser", JsonConvert.SerializeObject(getcart));
}
You just deleted a CartUser inside the ViewModel, and the Preferences have not changed.
According to your code, getcart is the List obtained using Preferences. You need to use getcart.Remove(itemcart); to delete an item. Then use your commented code to store it.
This is my list view it should contain the list of activities came from my SQLite database:
<ListView SeparatorVisibility="None" x:Name="lstActivity" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame StyleClass="lstframe" CornerRadius="0" BorderColor="Transparent" HasShadow="False">
<StackLayout StyleClass="lstContainer" VerticalOptions="CenterAndExpand">
<Grid>
<Label StyleClass="lstActivityName" Grid.Row="0" Grid.Column="0" Text="{Binding ActivityDescription}">
<Label.FontFamily>
<OnPlatform x:TypeArguments="x:String">
<On Platform="Android" Value="Poppins-Regular.otf#Poppins-Regular"/>
</OnPlatform>
</Label.FontFamily>
</Label>
<Switch Grid.Row="0" Grid.Column="1" IsToggled="{Binding Selected}" />
</Grid>
</StackLayout>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here is how I populate the list view this will return atleast five(5) activities:
public void Get_Activities()
{
try
{
var db = DependencyService.Get<ISQLiteDB>();
var conn = db.GetConnection();
var getActivity = conn.QueryAsync<ActivityTable>("SELECT * FROM tblActivity WHERE Deleted != '1' ORDER BY ActivityDescription");
var resultCount = getActivity.Result.Count;
if (resultCount > 0)
{
var result = getActivity.Result;
lstActivity.ItemsSource = result;
lstActivity.IsVisible = true;
}
else
{
lstActivity.IsVisible = false;
}
}
catch (Exception ex)
{
//Crashes.TrackError(ex);
}
}
Selected item binding:
public class SelectData
{
public bool Selected { get; set; }
}
Get selected Items on click:
private void BtnClose_Clicked(object sender, EventArgs e)
{
foreach (var x in result)
{
if (x.Selected)
{
// do something with the selected items
}
}
}
I posted another question regarding on multi-select list view my problem is I don't know how to proceed when I use the answers given to me. How can I get the the selected values because I will save the selected values to my database?
your Switch is bound to the Selected property of your model. Just iterate (or use LINQ) to get the items that are selected.
// you need to maintain a reference to result
foreach(var x in result)
{
if (x.Selected)
{
// do something with the selected items
}
}
LINQ
var selected = result.Where(x => x.Selected).ToList();
you will also need to have a class level reference to result
// you will need to change this to reflect the actual type of result
List<MyClass> result;
public void Get_Activities()
{
...
result = getActivity.Result;
...
For multi-select Listview, I have wrote a working example in my blog. Hope this helps : https://androidwithashray.blogspot.com/2018/03/multiselect-list-view-using-xamarin.html?view=flipcard
Am new to Wp7, developing the app with ListPicker and used SelectionChanged event to get selected data form listPicker but am having the problem with SelectionChanged event when am using this and getting NullReferenceException but when i used same code in button_Click that works perfectly and am getting the selected text
my c# code is :
private void listPicker1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListPickerItem lpi = (ListPickerItem)listPicker1.SelectedItem;//this code is working in click event
MessageBox.Show(lpi.Content.ToString());
}
my Xaml code is
<toolkit:ListPicker x:Name="listPicker1" Grid.Row="0" ExpansionMode="ExpansionAllowed" SelectionChanged="listPickerCountryLogin_SelectionChanged" HorizontalAlignment="Left" Margin="14,43,0,0" VerticalAlignment="Top" Width="436" FullModeHeader="Select Country" Background="White" BorderBrush="White">
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Country}" Width="250" />
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
<toolkit:ListPicker.FullModeItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Country}" Width="300" Margin="0,0,0,20" FontSize="44"/>
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>
but i want to get the text form SelectionChanged event?
how to achive this :)
thanks in advance
am also ran into same problem am also getting NullReferenceException
Try this works fine for me
1) If you are using static ListPickerItems means without DataBinding use this
private void listPicker1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListPickerItem lpi = (sender as ListPicker).SelectedItem as ListPickerItem;
MessageBox.Show("selected item is : " + lpi.Content);
}
2) Try this if You are using DataBinding to dispaly the listPickerItems
private void listPicker1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Countries item = (sender as ListPicker).SelectedItem as Countries;
MessageBox.Show("Selected Item is : " + item.Country);
}
here am assuming that you prepared a class Countries with country property for taht you need to typeCast to selected item to Countries class then only you get the result
I had this same problem when using SelectionChanged event in my listpicker, here is what I had:
// My listpicker is LpBluetoothPaired
private void LpBluetoothPaired_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
rcvData.Text = LpBluetoothPaired.SelectedItem.ToString();
}
But when opening the app it had an exception, so I fixed it:
private void LpBluetoothPaired_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (LpBluetoothPaired.SelectedItem != null) {
rcvData.Text = LpBluetoothPaired.SelectedItem.ToString();
}
}
it looks like the event is called when the application is opening but at that time there is still no selectedItem, so in order to avoid the exception and only fulfill the rcvData textBox I check if it isn''t null
Sometimes SelectionChanged event fires, when setting the ItemsSource from code behind. So, in such case the selectedItem may be null.
Hence, add this line in your SelectionChanged code and try.
private void listPicker1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(listPicker1.SelectedIndex == -1) //otherwise (listPicker1.SelectedItem == null) also works
return;
ListPickerItem lpi = (ListPickerItem)listPicker1.SelectedItem;//this code is working in click event
MessageBox.Show(lpi.Content.ToString());
}
If still problem persists, place a break point in the SelectionChanged handler, and observe the values
When data is loading to the listpicker it fires selectionchanged event.So for this put your code in Try-catch and For selectionchanged write this :
private void listPicker1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
Countries SelectedCountries =e.AddedItems[0] as Countries;
String SelectedCountry = SelectedCountries.Country;
}
catch
{
}
}
I am using the ExpanderView control available in the Silverlight Toolkit with some custom templates. It all works well, but when the ExpanderView is collapsed, and I click on the area below the Header where an item resides when the ExpanderView is expanded. The click event of that item fires.
How can i fix this? Should I somehow remove the tap commands or remove the ItemPanel when the ExpanderView is collapsed and add it again when it's being expanded?
<DataTemplate x:Key="CustomItemTemplate">
<Image delay:LowProfileImageLoader.UriSource="{Binding}" Width="156" Height="95" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<cmd:EventToCommand Command="{Binding Storage.ImageTapCommand, Source={StaticResource Locator}}" CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
</DataTemplate>
<toolkit:ExpanderView Grid.Column="1" Header="{Binding}"
Expander="{Binding}" IsExpanded="{Binding IsExpanded, Mode=TwoWay}"
ItemsSource="{Binding Files}" HeaderTemplate="{StaticResource CustomHeaderTemplate}"
ExpanderTemplate="{StaticResource CustomExpanderTemplate}"
ItemTemplate="{StaticResource CustomItemTemplate}" >
<toolkit:ExpanderView.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</toolkit:ExpanderView.ItemsPanel>
</toolkit:ExpanderView>
You can change the IsHitTestVisible property of the root UIElement for each of your expander items every time the ExpanderView is expanded/collapsed, and also just after initially binding the ExpanderView (hooking up to ExpanderView.LayoutUpdated works fine for that purpose). Here's an example that fixed the issue for me:
private void FixExpanderItemsInteractivity(ExpanderView expanderView)
{
foreach (var item in expanderView.Items)
{
ContentPresenter contentPresenter = expanderView.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter;
if (contentPresenter != null)
{
UIElement expanderItemRootElement = VisualTreeHelper.GetChild(contentPresenter, 0) as UIElement;
if(expanderItemRootElement != null)
{
expanderItemRootElement.IsHitTestVisible = expanderView.IsExpanded;
}
}
}
}
private void Expander_Expanded(object sender, RoutedEventArgs e)
{
FixExpanderItemsInteractivity(sender as ExpanderView);
}
private void Expander_Collapsed(object sender, RoutedEventArgs e)
{
FixExpanderItemsInteractivity(sender as ExpanderView);
}
private void Expander_LayoutUpdated(object sender, EventArgs e)
{
FixExpanderItemsInteractivity(sender as ExpanderView);
}