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
{
}
}
Related
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.
}
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);
}
I want to open a DatePicker from a popup. When I click the datepicker, the date input page (the one with spinners) opens behind the Popup.
How can the DatePicker go over the popup window and return to it after I select the date?
This is how I open the popup:
private void btnShowBuyNow_Click(object sender, RoutedEventArgs e)
{
Popup buyNowScreen;
buyNowScreen = new Popup();
buyNowScreen.Child =
new BuyNowScreen
("Buy this application and get rid of the ads!");
buyNowScreen.IsOpen = true;
buyNowScreen.VerticalOffset = 100;
buyNowScreen.HorizontalOffset = 25;
buyNowScreen.Closed += (s1, e1) =>
{
// Add you code here to do something
// when the Popup is closed
};
}
DatePicker in the popup's xaml file:
<toolbox:DatePicker x:Name="DatePick" Height="Auto" HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Top" Width="400" IsEnabled="True"/>
With Events:
Add a button in your PopUp with the DatePicker. When the button is clicked have an event to close the PopUp
XAML
<toolbox:DatePicker x:Name="DatePick" Height="Auto" HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Top" Width="400" IsEnabled="True"/>
<Button Click="DateAcceptedClick"/>
CodeBehind for Popup
public event DateAcceptedButtonClick DateAcceptedButtonEvent;
public delegate void DateAcceptedButtonClick (object sender, RoutedEventArgs e);
private void DateAcceptedClick(object sender, RoutedEventArgs e)
{
if (DateAcceptedButtonEvent!= null)
DateAcceptedButtonEvent(sender, e);
}
CodeBehind for Popup Parent
Popup BuyNowScreen;
private void btnShowBuyNow_Click(object sender, RoutedEventArgs e)
{
BuyNowScreen = new Popup();
BuyNowScreen.Child = new BuyNowScreen("Buy this application and get rid of the ads!");
BuyNowScreen.IsOpen = true;
BuyNowScreen.VerticalOffset = 100;
BuyNowScreen.HorizontalOffset = 25;
BuyNowScreen.DateAcceptedButtonEvent += new DateAcceptedButtonClick(PopupDateAcceptedButtonClick)
}
private void PopupDateAcceptedButtonClick(object sender, RoutedEventArgs e)
{
BuyNowScreen.IsOpen = false;
//Closed logic
}
I have a ListBox, here i am binding IList Like (Cities).
I want an event like OnItemDataBound in .NET in Windows Phone7.
Like when every city was binded (if 10 cities are this event will fire 10 times) this event will fire so that i have to do some more calculations on this event. In this event i have to find the object binded to the ListItem so that i can make some calculations. Is there any event in WP7 similar OnItemDataBound in .NET.
<ListBox Loaded="lstFlights_Loaded" Height="635" x:Name="lstFlights"
ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<Border CornerRadius="10" Margin="10">
<Border.Background>
<ImageBrush ImageSource="../Images/rowbg.png"></ImageBrush>
</Border.Background>
//Some data here
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
i am binding the data like below:
lstFlights.ItemsSource = objCities;
on Binding every city i want an event to populate some list items(like: i want to change the textblock text,etc) according to the City that binded to ListItem. To do this I need an event like OnItemDataBound in WP7. And I have list picker like below:
On SelectionChanged event also i want to change the list items.
And one more thing IList(objCities) is coming from the Service so I can't change that Object
so if i want to change any TextBlock in List Box i have do FindName and i have to assign calculated value for every city binded.
There is an CollectionChanged event in ObservableCollection collection for new elements added/removed.
ListBox provides some methods for accessing ListBoxItem. You can see them in list.ItemContainerGenerator class.
You can use it together to achieve needed results.
There is short example that shows how to make a red foreground to newly added items in some conditions (even or not):
ObservableCollection<string> items = new ObservableCollection<string>();
public MainPage()
{
InitializeComponent();
items.CollectionChanged += (s, e) =>
{
Dispatcher.BeginInvoke(() =>
{
if (e.NewItems != null)
{
foreach (var item in e.NewItems)
{
ListBoxItem listitem = (ListBoxItem)list.ItemContainerGenerator.ContainerFromItem(item);
if (DateTime.Parse(listitem.Content.ToString()).Second % 2 == 0)
{
listitem.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0));
}
}
}
});
};
list.ItemsSource = items;
}
private void AddButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
items.Add(DateTime.Now.ToLongTimeString());
}
private void RemoveButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
Random rnd = new Random();
if (items.Count > 0)
{
int index = rnd.Next(0, items.Count);
items.RemoveAt(index);
}
}
}
How about using the ItemsChanged event of your ListBox's ItemContainerGenerator instead?
this.myListBox.ItemContainerGenerator.ItemsChanged += new System.Windows.Controls.Primitives.ItemsChangedEventHandler(ItemContainerGenerator_ItemsChanged);
void ItemContainerGenerator_ItemsChanged(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
...
I am running into a very odd problem in c# and I just wanted to know what is causing this. I have my theories, but not entirely sure and just want to see if it can be reproduced.
Standard Pivot Page in wp7 silverlight 4.
<Pivot>
<PivotItem>
<Listbox Width="400" Height="500" x:Name="box" SelectionChanged="myhandle">
<ListBoxItem x:Name="item1">
<TextBlock Height="40" Width="200" Text="hi everyone!"/>
</ListBoxItem>
<ListBoxItem x:Name="item2">
<TextBlock Height="40" Width="200" Text="No Wai"/>
</ListBoxItem>
<ListBoxItem x:Name="item3">
<TextBlock Height="40" Width="200" Text="Ya Rly!"/>
</ListBoxItem>
</Listbox>
</PivotItem>
</Pivot>
In my C#, I have the following:
private void myhandle(object sender, SelectionChangedEventArgs args)
{
var selection ="";
selection = (sender as Listbox).SelectedIndex.ToString();
box.SelectedIndex = -1;
}
Here is the problem: Whenever I click on one of the three listboxitems, the myhandle code makes selection equal to the proper SelectedIndex, but then it hits the box.SelectedIndex =-1; line and then refires the myhandle function. In doing so, selection is now -1.
I have no idea why it is going back up the stack. This shouldn't be a recursive function.
My goal is to select the item, but then have the SelectedIndex back to -1 so that the person is able to select the item once again if need be, instead of changing to another item and back.
Sure there is an easy fix of throwing a switch function and checking to see if it's -1 already, but that doesn't solve the problem of the recursion.
Thanks for the time.
Everytime the selection is changed, the SelectionChanged event will fire. This includes clearing the selection, which includes setting SelectedIndex = -1 and even if you are already in a SelectionChanged handler.
You can do something like this:
private bool inMyHandle = false;
private void myhandle(object sender, SelectionChangedEventArgs args)
{
if (!this.isMyHandle) {
this.isMyHandle = true;
try {
var selection ="";
selection = (sender as Listbox).SelectedIndex.ToString();
box.SelectedIndex = -1;
}
finally {
this.isMyHandle = false;
}
}
}
The standard MS samples already have this in a standard Listbox selected item event.
Simply use the following in the event handler code:
private void ListBox_SelectionChanged(object sender,System.Windows.Controls.SelectionChangedEventArgs e)
{
// If selected index is -1 (no selection) do nothing
if (ListBox.SelectedIndex == -1)
return;
//Do Something
// Reset selected index to -1 (no selection)
ListBox.SelectedIndex = -1;
}
No need to have any boolean handlers, the function just nothing if "-1" is the current index.
All this is to compensate for the way that the standard listbox opperates.
If you use MVVM and bind to the "Selecteditem" / "SelectedIndex" properties you have to keep the same thing in mind.
You can check args.AddedItems.Count too:
private void myhandle(object sender, SelectionChangedEventArgs args)
{
if (args.AddedItems.Count > 0)
{
....
box.SelectedIndex = -1;
}
}