Event handling with LongListSelector and list item with checkbox - windows-phone-7

I've a LongListSelector with the following item template:
<DataTemplate x:Key="stopItemTemplate">
<Grid Margin="{StaticResource PhoneTouchTargetOverhang}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox VerticalAlignment="Top" HorizontalAlignment="Left" IsChecked="{Binding Checked}" Click="AlarmActivationClicked" />
<StackPanel Grid.Column="1" VerticalAlignment="Top">
<TextBlock Text="{Binding Stop.Name}" Style="{StaticResource PhoneTextLargeStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" TextWrapping="Wrap" Margin="12,-12,12,6"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Distanz:" Style="{StaticResource PhoneTextSmallStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" Width="120"/>
<TextBlock Text="{Binding Distance, Converter={StaticResource MyStringFormatConverter}, ConverterParameter=:1000:\{0:0.0\} km}" Style="{StaticResource PhoneTextSmallStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Alarm:" Style="{StaticResource PhoneTextSmallStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" Width="120"/>
<TextBlock Text="{Binding Alarm, Converter={StaticResource MyBooleanStringConverter}}" Style="{StaticResource PhoneTextSmallStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Vibration:" Style="{StaticResource PhoneTextSmallStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" Width="120"/>
<TextBlock Text="{Binding Vibration, Converter={StaticResource MyBooleanStringConverter}}" Style="{StaticResource PhoneTextSmallStyle}" FontFamily="{StaticResource PhoneFontFamilySemiBold}"/>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
And used as followed:
<controls:PivotItem Header="ziele">
<toolkit:LongListSelector x:Name="alarmList" Background="Transparent" IsFlatList="True"
ItemTemplate="{StaticResource stopItemTemplate}" SelectionChanged="AlarmListSelectionChanged" />
</controls:PivotItem>
The SelectionChanged event:
private void AlarmListSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var guid = ((AlarmItem)alarmList.SelectedItem).Id;
NavigationService.Navigate(new Uri(string.Concat("/AlarmDetailPage.xaml?id=", guid), UriKind.Relative));
}
To change details of an item I've subscribed the SelectionChanged event of the LongListSelector. That works as expected.
But if I tap on the checkbox - at first the clicked event of the checkbox is fired, but I don't recognize which checkbox was clicked (the property longlistselector.SelectedItem is old) and just after the SelectionChanged event has fired and try to navigate to the detail page like is happens if I intend to do that.
How can I separate these to events to avoid firing both? And how can I get the corresponding data item?
Thanks a lot...
Kind regards, Danny

You don't need listen to SelectionChanged event. In Click, Checked or Unchecked event handler you can get an item:
private void CheckBox_Checked(object sender, System.Windows.RoutedEventArgs e)
{
var guid = ((sender as CheckBox).DataContext as AlarmItem).Id;
NavigationService.Navigate(new Uri(string.Concat("/AlarmDetailPage.xaml?id=", guid), UriKind.Relative));
}

In your AlarmActivationClicked (event handler on the checkbox) you'll be able to get the dataitem of the item in the list that was click.
private void AlarmActivationClicked(object sender, RoutedEventArgs e)
{
var dataItem = ((FrameworkElement)sender).DataContext;
}
I am not seeing the event AlarmListSelectionChanged method being called after the AlarmActivationClicked method is called. If you click on the checkbox, the checkbox changes to checked, but it doesnt change the selection in the list box.

Related

How to access listboxitem template data when an event of it's item control is fired?

I want to access each listboxitem template control's(image and 4 textblock controls )data when the button is clicked from the following hierarchy.
<ListBox x:Name="lstBoxNearbyPlaces" ItemsSource="{Binding Items}" Grid.Row="2" Margin="0,10,0,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<Button Width="400" Height="150" Name="btnPlace" Click="btnPlace_Click_1">
<Button.Content>
<StackPanel Orientation="Horizontal" >
<Image Name="ImgPlace" Source="{Binding PlaceIconURL}" Width="50" />
<TextBlock Name="lblPlaceLat" Text="{Binding PlaceLatLocation}" Visibility="Collapsed"/>
<TextBlock Name="lblPlaceLng" Text="{Binding PlaceLongLocation}" Visibility="Collapsed"/>
<StackPanel Width="350" >
<TextBlock FontSize="20" Text="{Binding PlaceName}" Name="txtAddress" TextWrapping="Wrap" ></TextBlock>
<TextBlock FontSize="20" Text="{Binding PlaceVicinity}" Name="txtLocation" TextWrapping="Wrap"></TextBlock>
<Line MinHeight="5"></Line>
</StackPanel>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Is it possible to get or read the data of the every control here when the button click event is fired ?
You can get the binding object in the ListBox_SelectionChanged as the selected item.
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ItemModel model= listBox.SelectedItem as ItemModel ;
}
Or In the Buttonclick event you can get it as
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
ItemModel model = button.DataContext as ItemModel;
}
Here model is the object which you have bind to that template.

Access control inside a listbox without triggering selectionChanged event

For my listbox in windows phone I added a checkbox for each item with the help of this tutorial (option 2). Before I already had a SelectionChanged event for my listbox. How do I prevent firing the event, when the user just checks the checkbox? The SelectionChanged event should only fire when he hits the textbox in the listbox, but not the checkbox.
Thats my listbox:
<ListBox x:Name="toDoItemsListBox" ItemsSource="{Binding Source={StaticResource cvs}}" Grid.Row="1" Margin="12, 0, 12, 0" Width="440" SelectionChanged="goToNavigation" IsSynchronizedWithCurrentItem="False">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<CheckBox IsChecked="{Binding IsFavorite}" Height="48" Width="48" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked" Style="{StaticResource CheckBoxStyle1}"/>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Shortcut}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" />
<TextBlock Text="{Binding BuildingName}" TextWrapping="Wrap" Style="{StaticResource PhoneTextSubtleStyle}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
These are my check events:
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
ListBoxItem checedItem = this.toDoItemsListBox.ItemContainerGenerator.ContainerFromItem((sender as CheckBox).DataContext) as ListBoxItem;
if (checedItem != null)
{
checedItem.IsSelected = true;
}
}
private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
ListBoxItem checedItem = this.toDoItemsListBox.ItemContainerGenerator.ContainerFromItem((sender as CheckBox).DataContext) as ListBoxItem;
if (checedItem != null)
{
checedItem.IsSelected = false;
}
}
Also I have to mention that the selectionChanged event raises only when I check the checkbox. Not when I uncheck it.
I made it work without the selection changed event. As alternative I used a tap event:
<StackPanel Orientation="Vertical" Tap="StackPanel_Tap">
<TextBlock Text="{Binding Shortcut}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" />
<TextBlock Text="{Binding BuildingName}" TextWrapping="Wrap" Style="{StaticResource PhoneTextSubtleStyle}" />
</StackPanel>
and in Code behind I get my listitem with:
private void StackPanel_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
// Save current POI.
Object object = (sender as StackPanel).DataContext as Object;
...}

full-sized image in popup

I'm using ListBox with custom DataTemplate, in this DataTemplate I have two thumbnails, when user clicks on one of this images I need to display a popup with a full-sized image(something like lightbox in JavaScript). I tried to use the Popup control in the DataTemplate, but the popup is positioned to current element on ListBox, not centered in the screen, and I'm not able to make it modal. I also tried to use the Coding4Fun toolkit, but I can't find any documentation or do it without any help.
Here is code of listbox:
<ListBox MaxHeight="600" ItemsSource="{Binding Items}" x:Name="LooksList" u:ScrollViewerMonitor.AtEndCommand="{Binding FetchMoreDataCommand}" d:LayoutOverrides="GridBox" BorderThickness="0" Margin="0,0,0,62">
<ListBox.ItemTemplate>
<DataTemplate>
<views:LookListItem />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And views:LookListItem:
<Grid x:Name="LayoutRoot">
<StackPanel x:Name="MainPanel" Margin="0,53,0,0" Orientation="Horizontal">
<StackPanel x:Name="PhotosPanel" Margin="20,11,0,0" Width="198" Height="126" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderThickness="3" BorderBrush="White" Margin="0" HorizontalAlignment="Left" Width="93" Height="126">
<Image Source="{Binding Photo1.Thumb}" VerticalAlignment="Center" Tap="Image_Tap" />
</Border>
<Border BorderThickness="3" BorderBrush="White" Margin="12,0,0,0" HorizontalAlignment="Right" Width="93" Height="126">
<Image Source="{Binding Photo2.Thumb}" VerticalAlignment="Center" />
</Border>
</StackPanel>
</StackPanel>
</Grid>
Photo1 and Photo2 should be clickable and after click it should be a popup.
Thanks in advance!
There are a few ways you can go about doing this. I'll show how you can do this with a little code behind.
In your xaml:
<Grid>
<ListBox ItemsSource="{Binding MyItems}" ItemTemplate="{Binding MyTemplate}"
SelectionChanged="ListBox_SelectionChanged"/>
<Popup x:Name="Popup">
<Grid>
<ToggleButton Content="X"
IsChecked="{Binding IsOpen, ElementName=Popup, Mode=TwoWay}"
HorizontalAlignment="Right" VerticalAlignment="Top"/>
<Image x:Name="PopupImage"/>
</Grid>
</Popup>
</Grid>
In your code behind:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs args)
{
ListBox listBox = (ListBox)sender;
MyImageObject obj = (MyImageObject)listBox.SelectedItem;
ImagePopup.Source = MyImageObjct.LargeImageSource;
Popup.IsOpen = true;
// Unselect item so user can "reselect" it -- If you need item later, save it somewhere
listBox.SelectedItem = null;
}
// Handle the back key button to close the popup
protected override void OnBackKeyPress(CancelEventArgs e)
{
if(Popup.IsOpen)
{
Popup.IsOpen = false;
e.Cancel = true;
}
}
UPDATE BASED ON LATEST INFO
If you do not need your view in a separate UserControl (no logic, only placement of controls) you can still use the example, but instead of listening to the SelectionChanged event, listen to the Tap event of each Image.
<ListBox MaxHeight="600" ItemsSource="{Binding Items}" x:Name="LooksList"
BorderThickness="0" Margin="0,0,0,62">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="MainPanel" Margin="0,53,0,0" Orientation="Horizontal">
<StackPanel x:Name="PhotosPanel" Margin="20,11,0,0" Width="198" Height="126" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderThickness="3" BorderBrush="White" Margin="0" HorizontalAlignment="Left" Width="93" Height="126">
<Image Source="{Binding Photo1.Thumb}" VerticalAlignment="Center" Tap="Image1_Tap" />
</Border>
<Border BorderThickness="3" BorderBrush="White" Margin="12,0,0,0" HorizontalAlignment="Right" Width="93" Height="126">
<Image Source="{Binding Photo2.Thumb}" VerticalAlignment="Center"
Tap="Image2_Tap" />
</Border>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
The event of for Tap events would look something like
private void Image1_Tap(object sender, GestureEventArgs gestureEventArgs)
{
MyImageObject obj = ((FrameworkElement)sender).DataContext as MyImageObject;
// This is the event for Image1 Thumb, so show the Image1 Large
ShowPopup(obj.Photo1.Large);
}
If you do need a separate UserControl
You could create an "ImageOverlay" view much like in my Custom MessageBox Post. In your LookListItem view subscribe to the tap event for both thumbs
<Grid x:Name="LayoutRoot">
<StackPanel x:Name="MainPanel" Margin="0,53,0,0" Orientation="Horizontal">
<StackPanel x:Name="PhotosPanel" Margin="20,11,0,0" Width="198" Height="126" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Border BorderThickness="3" BorderBrush="White" Margin="0" HorizontalAlignment="Left" Width="93" Height="126">
<Image Source="{Binding Photo1.Thumb}" VerticalAlignment="Center" Tap="Thumb1_Tap" />
</Border>
<Border BorderThickness="3" BorderBrush="White" Margin="12,0,0,0" HorizontalAlignment="Right" Width="93" Height="126">
<Image Source="{Binding Photo2.Thumb}" VerticalAlignment="Center" Tap="Thumb2_Tap" />
</Border>
</StackPanel>
</StackPanel>
In the tap events show the ImageOverlay control
private void Thumb1_Tap(object sender, GestureEventArgs gestureEventArgs)
{
ShowOverlay(Photo1.Large);
}
private void Thumb2_Tap(object sender, GestureEventArgs gestureEventArgs)
{
ShowOverlay(Photo2.Large);
}
private void ShowOverlay(ImageSource source)
{
ImageOverlay overlay = new ImageOverlay();
overlay.ImageSource = source;
overlay.Show();
}

Reloading listbox in WP7

I am using List to bind a listbox which is as follows:
<ListBox x:Name="ContentPanel" SelectionChanged="onSelectionChanged" Background="LightGray" Grid.Row="2">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Name="{Binding title}" Height="165" Margin="25,5,25,0" Width="430">
<Border BorderThickness="1" Height="165" BorderBrush="Gray">
<toolkit:ContextMenuService.ContextMenu >
<toolkit:ContextMenu IsZoomEnabled="False">
<toolkit:MenuItem Name="Delete" Header="Delete Message" Click="DeleteMessage_Click" >
</toolkit:MenuItem>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<StackPanel Orientation="Vertical">
<StackPanel>
<TextBlock Text="{Binding title}" Margin="5,0,0,0" FontSize="25" Foreground="Black"/>
<TextBlock Text="{Binding msgFrom}" Padding="5" TextWrapping="Wrap" Foreground="Gray" FontSize="20"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5,13,0,0" FontSize="24" Foreground="WhiteSmoke" Text="{Binding msgReceivedOn}"/>
<toolkit:ToggleSwitch Margin="170,10,0,0" IsChecked="{Binding msgStatus}" Unchecked="UnChecked" Background="LightBlue" Checked="Checked"/>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
At first data is successfully loaded. But when I use the Contextmenu to remove the item and reload the listbox.. it fires an exception. Code to handle the context menu click is:
private void DeleteMessage_Click(object sender, RoutedEventArgs e)
{
MenuItem item = sender as MenuItem;
Message message = (Message)item.DataContext;
MessageBoxResult result = MessageBox.Show("Are you sure to delete the message??", "Confirmation", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.Cancel)
return;
else
{
ContentPanel.Items.Remove(message);
lstMessage.Remove(message);
}
ContentPanel.ItemSource = lstMessage;
}
But it this code is not working. So any suggestions?
You don't need each time to bind collection to a list. Also, when you remove an item from your collection, it should disappear also in the list (if binding setup properly). I think you have not ObservableCollection, so you need manage items manually. Please, consider to use ObservableCollection.
Your code should looks like:
lstMessage.Remove(message); //it must raises CollectionChanged event automatically
And this lines is unnecessary:
ContentPanel.Items.Remove(message);
ContentPanel.ItemSource = lstMessage;

getting information from a data binding listBox for a new page

I have a news section that consist of listBox binding from a ViewModel (listBox include)
<controls:PanoramaItem x:Name="News" Header="News">
<!--Double line list with image placeholder and text wrapping-->
<ListBox x:Name="News_ListBox" Margin="0,0,-12,0" ItemsSource="{Binding Items}"SelectionChanged="SelectNewsItem">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
<!--Replace rectangle with image-->
<Rectangle Height="100" Width="100" Fill="#FFE5001b" Margin="12,0,9,0"/>
<StackPanel Width="311">
<TextBlock Name="NewsTitle" Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Name="NewsDetail" Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PanoramaItem>
I want to do that when some one click on a news item it takes him to a new page and view the full information. I did the selectionChanged event but I don't know How to get the news information from the binding?
Plz help me.
Thanks,
a typical SelectionChanged handler for these cases should look like this:
private void lstItems_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (lstItems.SelectedIndex == -1) return;
var item = lstItems.SelectedItem as MyClass;
// do navigation here
lstItems.SelectedIndex = -1;
}
This is a part of DataBound template in visual studio for WP7.

Resources