In my Windows/Windows Phone Universal App, I have ListView with a MenuFlyout in my XAML layout. The ListView includes a list of people. Tapping on a list item reveals the flyout with options to email or call the person. Right now I am using the Tag property of the MenuFlyoutItem to hold the email address and phone number, but I also want to be able to get the name of the person so I can send that when I open the email composer or phone dialer.
I am using the Tag element to store the basic information, but I want to access the name. How do I do this? Using extra properties? Somehow accessing the data binding of the parent object?
XAML:
<ListView
x:Name="itemPositions"
AutomationProperties.AutomationId="ItemListView"
AutomationProperties.Name="Items In Group"
TabIndex="1"
Grid.Row="1"
ItemsSource="{Binding Positions}"
SelectionMode="None"
IsSwipeEnabled="false"
Margin="0,0,0,0">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Tapped="Grid_Tapped">
<FlyoutBase.AttachedFlyout>
<MenuFlyout>
<MenuFlyoutItem IsEnabled="{Binding IsFilled}" Tag="{Binding Email}" x:Name="sendEmail" Text="email" Click="sendEmail_Click" />
<MenuFlyoutItem IsEnabled="{Binding IsFilled}" Tag="{Binding Phone}" x:Name="sendCall" Text="call" Click="sendCall_Click" />
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Visibility="{Binding IsVerified, Converter={StaticResource BoolToInvisible}}" Margin="0,0,0,5" Background="Firebrick" Width="10" Height="70" />
<Border Visibility="{Binding Required, Converter={StaticResource BoolToVisible}}">
<Border Grid.Column="0" Visibility="{Binding IsFilled, Converter={StaticResource BoolToInvisible}}" Margin="0,0,0,5" Background="Gold" Width="10" Height="70" />
</Border>
<StackPanel Margin="10,0,0,10" Grid.Column="1">
<TextBlock Text="{Binding PositionName}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>
<TextBlock Text="{Binding DisplayName}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C#:
private void Grid_Tapped(object sender, TappedRoutedEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (element != null) FlyoutBase.ShowAttachedFlyout(element);
}
private async void sendEmail_Click(object sender, RoutedEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
Windows.ApplicationModel.Email.EmailMessage mail = new Windows.ApplicationModel.Email.EmailMessage();
mail.Subject = "Leadsheet Position Assignment";
mail.To.Add(new Windows.ApplicationModel.Email.EmailRecipient(element.Tag.ToString()));
await Windows.ApplicationModel.Email.EmailManager.ShowComposeNewEmailAsync(mail);
}
private void sendCall_Click(object sender, RoutedEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
Windows.ApplicationModel.Calls.PhoneCallManager.ShowPhoneCallUI(element.Tag.ToString(), "");
}
I thin you should be able to do this for example by checking the DataContext of clicked Grid or MenuItem:
private void Grid_Tapped(object sender, TappedRoutedEventArgs e)
{
Item yourItem = (sender as Grid).DataContext as Item;
FrameworkElement element = sender as FrameworkElement;
if (element != null) FlyoutBase.ShowAttachedFlyout(element);
}
// you can also do the same in your menu items:
private async void sendEmail_Click(object sender, RoutedEventArgs e)
{
Item yourItem = (sender as MenuFlyoutItem).DataContext as Item;
FrameworkElement element = sender as FrameworkElement;
Windows.ApplicationModel.Email.EmailMessage mail = new Windows.ApplicationModel.Email.EmailMessage();
mail.Subject = "Leadsheet Position Assignment";
mail.To.Add(new Windows.ApplicationModel.Email.EmailRecipient(element.Tag.ToString()));
await Windows.ApplicationModel.Email.EmailManager.ShowComposeNewEmailAsync(mail);
}
Item above is your ItemClass which you use in Positions set as ItemsSource. Once you have the clicked item, the rest should be easy. With this you also no longer need to bind in Tag property.
Related
I am trying to update a data-binded list view.
This is the desired behaviour:
The user writes the title of the item he/she likes to add to the list and submits his input with the enter key.
The list should update, but it doesn't.
private void NewSubject_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
TextBox newSubject = sender as TextBox;
Subjects.Add(new Subject { Title = newSubject.Text });
SubjectsList.ItemsSource = Subjects;
newSubject.Text = "";
}
}
this is the xaml code excerpt:
<DockPanel Margin="4">
<TextBox x:Name="NewSubject" KeyDown="NewSubject_KeyDown" DockPanel.Dock="Bottom" Margin="0 8 0 0" Padding="4" />
<ListView Name="SubjectsList" ItemsSource="{Binding Subjects}" DockPanel.Dock="Bottom">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DockPanel>
Where could be my mistake?
I'm working on Windows Phone 8.1 RT project and i want to get my binding item when mapcontrolSP tapped.
<Maps:MapControl x:Name="Map" MapServiceToken="abcdef-abcdefghijklmno">
<Maps:MapItemsControl x:Name="mapitem" ItemsSource="{Binding}">
<Maps:MapItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="mapcontrolSP" Orientation="Horizontal" Background="Red" Tapped="ItemStckPanel">
<Image Source="Assets/ico-venue.png" Height="45" Width="45"
Maps:MapControl.Location="{Binding Geopoint}"
Maps:MapControl.NormalizedAnchorPoint="{Binding Anchor}"/>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5">
<TextBlock FontSize="15" Foreground="White" Text="{Binding name}"/>
<TextBlock FontSize="15" Foreground="White" Text="{Binding address}"/>
<TextBlock FontSize="15" Foreground="White" Text="{Binding distance}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</Maps:MapItemsControl.ItemTemplate>
</Maps:MapItemsControl>
</Maps:MapControl>
I create a tapped event on the StackPanel element but item is null:
private void ItemStckPanel(object sender, TappedRoutedEventArgs e)
{
var item = sender as FsqBasicItem;
MessageDialog dialog = new MessageDialog(item.name);
dialog.ShowAsync();
}
How can i get item ?
Fast solution:
private void ItemStckPanel(object sender, TappedRoutedEventArgs e)
{
var stackPanel = sender as StackPanel;
var item = stackPanel.DataContext as FsqBasicItem;
if(item != null)
{
MessageDialog dialog = new MessageDialog(item.name);
dialog.ShowAsync();
}
}
I am parsing some JSON data using Newtonsoft.NET for my WP8 app in C#/XAML and everything works fine except the binding of NavigationUri to the HyperlinkButton. Here is the DataTemplate of my databound LongListSelector:
<DataTemplate>
<StackPanel Margin="10 10 10 20" Background="{StaticResource PhoneAccentBrush}">
<TextBlock Text="{Binding MovieTitle }" TextWrapping="Wrap" FontSize="18" />
<TextBlock Text="{Binding ImdbCode }" TextWrapping="Wrap" FontSize="18" />
<HyperlinkButton NavigateUri="{Binding ImdbLink}">View on IMDB</HyperlinkButton>
<Image Source="{Binding MovieCover}" Width="300" Height="300" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding ImdbLink}" TextWrapping="Wrap" FontSize="18" />
</StackPanel>
</DataTemplate>
This way everything is loaded correctly but the HyperLinkButton doesn't navigate to the Uri.
What should I do to make sure the navigation works?
If it is not possible with HyperLinkButton then can I add a regular button to which I could pass the url so that OnClick event can navigate to url.
Assuming the url is correct the webbrowser can be activated like this:
XAML
<HyperlinkButton NavigateUri="{Binding ImdbLink}"
Click="NavigateButton_Click">View on IMDB</HyperlinkButton>
C#
private void NavigateButton_Click(object sender, RoutedEventArgs e)
{
var hyperlinkButton = sender as HyperlinkButton;
if(hyperlinkButton == null)
{
return;
}
ShowInBrowser(hyperlinkButton.NavigateUri);
}
private void ShowInBrowser(Uri url)
{
Microsoft.Phone.Tasks.WebBrowserTask wbt =
new Microsoft.Phone.Tasks.WebBrowserTask();
wbt.Uri = url;
wbt.Show();
}
This is because you have no RequestNavigate method. Try:
<HyperlinkButton NavigateUri="{Binding ImdbLink}" RequestNavigate="Hyperlink_RequestNavigate">View on IMDB</HyperlinkButton>
and in your code behind for the view put
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}
or however you want to deal with that click event (i.e. open a new webview with that as the url)
I am trying to use context menu in a listbox to run some come code.that require data from which item it originated.the click event context menu item shows msg but i found that it doent not access the originating listview item .
<Canvas x:Name="LeftCanvas" Grid.Column="0" Grid.Row="1" Margin="5,0,0,0">
<StackPanel>
<TextBlock Text="Unseated Guests" Background="Blue" Foreground="White" FontFamily="Verdana" FontSize="11" FontWeight="Bold" Height="17" Width="150" HorizontalAlignment="Left" TextAlignment="Center" Padding="0,4,5,2"></TextBlock>
<ListBox x:Name="UnseatedPersons" ItemsSource="{Binding}" Height="218" Width="150" BorderBrush="Blue" BorderThickness="2" HorizontalAlignment="Left" Padding="3,2,2,2" src:FloorPlanClass.DragEnabled="true" MouseEnter="UnseatedPersons_MouseEnter"
MouseLeave="SourceListBox_MouseLeave">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<DockPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Archive Info" Click="bt_click" />
<MenuItem Header="Guest Info" />
</ContextMenu>
</DockPanel.ContextMenu>
<Image Name="imgPerson" Source="{Binding ImagePath}" />
<TextBlock Name="txtPersonName" Text="{Binding PersonName}" Padding="2,4,0,0" />
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Canvas>
C#:
void bt_click(object sender, RoutedEventArgs e)
{
MessageBox.Show("my message");
}
Use the sender by casting them to MenuItem. Like:
void bt_click(object sender, RoutedEventArgs e)
{
MenuItem originalItem = (MenuItem)sender;
MessageBox.Show(string.Format("clicked from \"{0}\"", originalItem.Name));
}
The sender in the click event will be the MenuItem you clicked.
Its parent will be the ContextMenu
The PlacementTarget of the ContextMenu will be the DockPanel.
The DockPanel will have the ListBoxItem as an ancestor in the Visual Tree
So to get the ListBoxItem in the click event you can use something similar to this
private void bt_click(object sender, RoutedEventArgs e)
{
MenuItem clickedMenuItem = sender as MenuItem;
ContextMenu contextMenu = clickedMenuItem.Parent as ContextMenu;
DockPanel dockPanel = contextMenu.PlacementTarget as DockPanel;
ListBoxItem listBoxItem = GetVisualParent<ListBoxItem>(dockPanel);
MessageBox.Show(listBoxItem.ToString());
// Update. To display the content of the ListBoxItem
MessageBox.Show(listBoxItem.Content.ToString());
}
public static T GetVisualParent<T>(object childObject) where T : Visual
{
DependencyObject child = childObject as DependencyObject;
// iteratively traverse the visual tree
while ((child != null) && !(child is T))
{
child = VisualTreeHelper.GetParent(child);
}
return child as T;
}
I am populating a listbox from a webcclient, the data is binded to the listbox and not saved anywhere..
Id like to access binded information when the user selects from the listbox
im having trouble accessing the value of a text block from the SelectionChanged event..
<ListBox x:Name="UsersListBox" ItemsSource="{Binding Items}" Height="471" VerticalAlignment="Top" HorizontalAlignment="Left" Width="457" SelectionChanged="TargetsListBox_SelectionChanged" Grid.ColumnSpan="2">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432" Orientation="Horizontal">
<Image x:Name="ImageAddIcon" Source="blkAdd.png" Height="60" Width="71" VerticalAlignment="Stretch" />
<Image x:Name="ImagePointer" Source="blkClick.png" Height="60" Width="71" VerticalAlignment="Stretch" />
<StackPanel>
<TextBlock Name="txtID" Text="{Binding PlayerID}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" Foreground="#FF8A9A8A" Visibility="Collapsed" />
<TextBlock Name="txtNick" Text="{Binding Nickname}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}" Foreground="#FF8A9A8A" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Id like to access the PlayerID from this dynamicly populated list(from webservice) on a onselected basis
private void TargetsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string ID = UsersListBox.SelectedItem ???PlayerID or txtID???;
}
i just want to get the player id that is binded to the listbox with a selection changed event ANY IDEAS!!!!!!!!! <3
Assuming that "Items" is a ObservableCollection:
private void TargetsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = sender as ListBox;
var selectedItem = listBox.SelectedItem as Player;
if (selectedItem != null)
{
string id = selectedItem.PlayerID
string nick = selectedItem.NickName;
}
}