I Have an image within an ItemTemplate of ListBox, on the Tap event I execute an action.
on the SelectionChanged event of the ListBox I navigate to another Page when user does not tap on the image: my problem is the order of the these events: the selectionChanged event occurs before the tap event then the navigation occurs before the event Tap
how can I solve this problem? help please
In selectionChanged I test if it is not refresh (a boolean that I set to true when image Tap event trigged) I navigate to another page and if it is refresh I do not navigate
with a LongListSelector it works well because tap events is trigged first but not with ListBox (ReorderListBox exactly).
My datatemplate contains others controls:
<DataTemplate x:Key="ItemTemplate" >
<Grid Height="150" Width="408" Background="White" Margin="0,0,0,14">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<toolkit:ContextMenuService.ContextMenu >
<toolkit:ContextMenu Height="150" Background="#26AA99" BorderBrush="Transparent" Unloaded="ContextMenu_Unloaded" >
<toolkit:MenuItem Header="{Binding Path=LocalizedResources.PinToStart, Source={StaticResource LocalizedStrings}}" Foreground="#FFFFFF" FontWeight="Normal" FontSize="26" Click="MIPinSchedule_Click" />
<toolkit:MenuItem Header="{Binding Path=LocalizedResources.Delete, Source={StaticResource LocalizedStrings}}" Foreground="#FFFFFF" FontWeight="Normal" FontSize="26" Click="MIDeleteSchedule_Click" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<Border Grid.Row="0" Background="{Binding LineColor}" Height="14" Width="408"/>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="12,0,0,0" Foreground="#00418D" FontWeight="SemiBold" FontSize="26"/>
<Grid >
<!--Les deux prochais passages-->
<phone:LongListSelector
ItemsSource="{Binding NextStopCollection, Mode=TwoWay}"
LayoutMode="List"
ItemTemplate="{StaticResource ItemTemplate2}" />
<!--Boutton refresh qui s'affiche au bout de 20 secondes-->
<Image VerticalAlignment="Center" Margin="0,0,12,0" HorizontalAlignment="Right" Height="48" Width="48"
Source="/Assets/Refresh.png" Tap="Refresh_Tap"
Visibility="{Binding ElementName=reorderListBox, Path=DataContext.IsOutOfDate,Converter={StaticResource BooleanToVisibilityConverter}}"/>
</Grid>
</Grid>
</DataTemplate>
private void reorderListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var rlb = sender as ReorderListBox.ReorderListBox;
if (rlb.SelectedItem == null)
return;
if (!viewModel._isRefresh)
{
var selectedItem = rlb.SelectedItem as MyObject;
NavigationService.Navigate(new Uri(MyUri, UriKind.Relative));
}
_isRefresh = false;
rlb.SelectedItem = null;
}
private void Refresh_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
//Do action
_isRefresh = true;
}
I would suggest you discard the SelectionChanged event completely and instead add a Tap event on the Grid in your DataTemplate.
Related
I have Windows 8.1 Hub App that will eventually be released for tablets. I want to add MenuFlyout to GridView. So if I right click or hold then flyout will display. I've gone through several videos, tutorials etc. but none of them relates to GridView. Only for ListView on WindowsPhone. So none of them show how I should approach.
Is it possible? How I should deal with it?
HubSection
This is how my Hubsection with GridView looks like.
<HubSection x:Name="CalcButtons" x:Uid="calculator" Header="{Binding Res.calc2Header, Source={StaticResource SharedStrings}}">
<DataTemplate>
<GridView
ItemsSource="{Binding}"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Items In Group"
ItemTemplate="{StaticResource StandardCalcButton}"
SelectionMode="None"
IsItemClickEnabled="True" Margin="0,0,0,0" ItemClick="GridView_ItemClick">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</DataTemplate>
</HubSection>
StandardCalcButton
I've created MenuFlayout as resource in App.xaml and attached it to GridViewItem DataTemplate. So it looks like this.
<MenuFlyout x:Key="CalcFlyout">
<MenuFlyoutItem Text="Test1"/>
<MenuFlyoutItem Text="Test2"/>
</MenuFlyout>
<DataTemplate x:Key="StandardCalcButton" >
<Grid Height="180" Width="180" Margin="5,5,5,5" FlyoutBase.AttachedFlyout="{StaticResource CalcFlyout}" >
<Border Height="180" Background="{StaticResource AppYellow}">
<StackPanel Grid.Row="1" Margin="0,0,0,0">
<Image Source="{Binding ImagePath}" AutomationProperties.Name="{Binding Title}" Height="130" Width="180"/>
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" TextLineBounds="Tight" TextAlignment="Center"/>
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource BodyTextBlockStyle}" TextWrapping="NoWrap" TextLineBounds="Tight" LineStackingStrategy="BlockLineHeight" TextTrimming="CharacterEllipsis" TextAlignment="Center" />
</StackPanel>
</Border>
</Grid>
</DataTemplate>
This is how I want to make Flyout to open in GridView_ItemClicked
private void GridView_ItemClick(object sender, ItemClickEventArgs e){
FrameworkElement senderElement = e.ClickedItem as FrameworkElement;
if (senderElement == null)
{
Debug.WriteLine("null");
return;
} else
{
FlyoutBase flyoutBase = FlyoutBase.GetAttachedFlyout(senderElement);
flyoutBase.ShowAt(senderElement);
}
}
''ClickedItem'' is object which I deliver in ''GridView.DataContext'' so there is no way that it will be castable to FrameworkElement.
Now I'm stuck. I'll be thankful for any guidance.
You can try the following:
private void GridView_ItemClick(object sender, ItemClickEventArgs e)
{
var gridViewItemsControl = sender as ItemsControl;
var clickedItemContainer = gridViewItemsControl.ContainerFromItem(e.ClickedItem);
Debug.WriteLine(clickedItemContainer);
var clickedGridViewItem = clickedItemContainer as GridViewItem;
var clickedItemGrid = clickedGridViewItem.ContentTemplateRoot as Grid;
FlyoutBase flyoutBase = FlyoutBase.GetAttachedFlyout(clickedItemGrid);
flyoutBase.ShowAt(clickedItemGrid);
}
Hope i helps! :)
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.
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;
...}
I have listbox in my WP7 that uses the below DataTemplete to display the list items
<DataTemplate x:Key="MetaDataTemplate">
<Grid Width="440" Margin="4,12,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="64"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="download" Visibility="{Binding DownloadVisible}" Command="{Binding Download}"/>
<toolkit:MenuItem Header="get link" Command="{Binding GetLink}"/>
<toolkit:MenuItem Header="delete" Command="{Binding Delete}"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<Image Height="64" Width="64" Source="{Binding Thumb}" Stretch="UniformToFill" />
<TextBlock Text="{Binding MetaData.Name, Mode=OneWay}" VerticalAlignment="Center" Margin="12,0,0,0"
Style="{StaticResource MetaDataHeaderStyle}" Grid.Column="1" />
</Grid>
</DataTemplate>
defining the context menu data template makes it quite impossible to close the menu on pressing the back button! Does anyone faced this problem? How did you solve it?
I searched for the solution on internet, but couldn't find one. Any help is appreciated.
A way to do it is to have a ContextMenu variable in the code behind, and have an event handler for the Opened event of the ContextMenu in the template.
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu Opened="ContextMenu_Opened">
<toolkit:MenuItem Header="stuff">
</toolkit:MenuItem>
<toolkit:MenuItem Header="more stuff">
</toolkit:MenuItem>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
In the Opened event handler, set the ContextMenu variable to that instance (i.e. sender).
private void ContextMenu_Opened(object sender, RoutedEventArgs e)
{
menu = sender as ContextMenu;
}
Finally, override OnBackKeyPress, so that if the variable is not null, and the menu is open, then close the menu and cancel the back event.
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if (menu != null && menu.IsOpen)
{
menu.IsOpen = false;
e.Cancel = true;
}
base.OnBackKeyPress(e);
}
That should do it! Let me know if you have any issues, or need me to paste the full code.
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.