I had a problem with passing a parsed string to a button click event. It was solved in this thread here, but now there's another small problem but it's with LINQ TO XML. I'm making a page which will show all of the apps that I make and will be updated with XML which I'll host on my server. On that page I'm parsing the icon, the title, the price and the marketplace Uri of the apps. I'm binding the Uri and the title of the apps to a single hyperlinkbutton but the problem is that every hyperlinkbutton on the list takes me to the same marketplace page. How can I fix it so every hyperlinkbutton navigates to a different page?
Here's the code:
public partial class MorePage : PhoneApplicationPage
{
private string appLink;
public MorePage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
WebClient client = new WebClient();
Uri uritoXML = new Uri("http://www.allanhaapalainen.com/AppsXML/MorePageXML.xml", UriKind.RelativeOrAbsolute);
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(uritoXML);
base.OnNavigatedTo(e);
}
public void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
XDocument moreApps = XDocument.Parse(e.Result);
morePageAppList.ItemsSource = from Apps in moreApps.Descendants("App")
select new MoreApps
{
MoreImage = Apps.Element("link").Value,
Price = Apps.Element("price").Value,
Title = Apps.Element("title").Value
};
var attribute = (from Apps in moreApps.Descendants("App")
select new MoreApps
{
AppAttribute = (string)Apps.Attribute("id").Value
}).FirstOrDefault();
string appAttr = attribute.AppAttribute;
var link = (from Apps in moreApps.Descendants("App")
where Apps.Attribute("id").Value == appAttr
select new MoreApps
{
AppUri = (string)Apps.Element("marketplace").Value
}).FirstOrDefault();
appLink = link.AppUri;
}
private void App_Name_Click(object sender, RoutedEventArgs e)
{
ShowMarket(appLink);
}
private void ShowMarket(string id)
{
MarketplaceDetailTask marketplaceDetailTask = new MarketplaceDetailTask();
marketplaceDetailTask.ContentIdentifier = id;
marketplaceDetailTask.Show();
}
}
AND THE XAML:
<ListBox Height="500" Width="Auto" Name="morePageAppList" Margin="0,0,0,0" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="173">
<Image Source="{Binding MoreImage}" Height="Auto" Width="Auto" />
<StackPanel Orientation="Vertical">
<HyperlinkButton Name="appName" Content="{Binding Title}" Margin="15,60,0,0" Click="App_Name_Click" />
<TextBlock Name="price" Text="{Binding Price}" Margin="28,0,0,0" Foreground="#FFBD0000" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Like I mentioned in your previous post, you can use the tag parameter. Update your DataTemplate
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="173">
<Image Source="{Binding MoreImage}" Height="Auto" Width="Auto" />
<StackPanel Orientation="Vertical">
<HyperlinkButton Name="appName" Content="{Binding Title}" Tag="{Binding}" Margin="15,60,0,0" Click="App_Name_Click" />
<TextBlock Name="price" Text="{Binding Price}" Margin="28,0,0,0" Foreground="#FFBD0000" />
</StackPanel>
</StackPanel>
</DataTemplate>
then in your event
private void App_Name_Click(object sender, RoutedEventArgs e)
{
var button = (HyperLinkButton)sender;
var selectedApp = (MoreApps)button.Tag;
ShowMarket(selectedApp.AppUri);
}
Related
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.
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'm making an atom reader for Windows Phone. The mainpage.xaml.cs code looks like this:
void ywc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
StringReader sr = new StringReader(e.Result);
var reader = XmlReader.Create(sr);
var document = XDocument.Load(reader);
XNamespace atom = "http://www.w3.org/2005/Atom";
XNamespace media = "http://search.yahoo.com/mrss/";
var YTitems = from entry in document.Descendants(atom + "entry")
select new RSSFeed
{
ImageSRC = entry.Element(media + "group").Element(media + "thumbnail").Attribute("url").Value,
Title = entry.Element(atom + "title").Value,
pubDate = entry.Element(atom + "published").Value.Substring(0, 10),
VideoURL = entry.Element(media + "group").Element(media + "content").Attribute("url").Value
};
YoutubeList.ItemsSource = YTitems.ToList();
}
private void screenshot_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Uri uri = new Uri("insertyoutubeurihere");
WebBrowserTask webBrowserTask = new WebBrowserTask();
webBrowserTask.Uri = uri;
webBrowserTask.Show();
}
The mainpage.xaml code looks like this:
<phone:LongListSelector Margin="0,0,-22,0" Name="YoutubeList">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="12,2,0,4" Width="Auto">
<Image x:Name="screenshot" Source="{Binding Path=ImageSRC}" Width="150" Tap="screenshot_Tap"/>
<StackPanel Width="311" Margin="8,-7,0,0">
<TextBlock Text="{Binding Path=Title}" TextWrapping="Wrap" Margin="10,0" Style="{StaticResource PhoneTextLargeStyle}" FontSize="{StaticResource PhoneFontSizeMedium}" />
<TextBlock Text="{Binding Path=pubDate}" TextWrapping="Wrap" Margin="10,-2,10,0" Style="{StaticResource PhoneTextSubtleStyle}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
I don't really know how I can link the uri to the corresponding VideoURL.
So when he user taps, than it opens the webpage with the url of the video.
You can use a Command binding. Instead of two textblocks you can use a button or Hyperlink. Bind the Command property of the button or hyperlink to an ICommand property of your viewmodel.
More information about ICommand: http://msdn.microsoft.com/library/vstudio/system.windows.input.icommand
In case you are using MVVM Light, you could also take a look at the RelayCommand class.
this:
<StackPanel>
<HyperlinkButton Height="310"
Width="200"
NavigateUri="{Binding Path=ImageSRC}"
Name="hyperlinkButton1"
TargetName="_blank">
<HyperlinkButton.Background>
<ImageBrush ImageSource="{Binding Path=ImageSRC}"/>
</HyperlinkButton.Background>
</HyperlinkButton>
...
</StackPanel>
Just use this:
System.Diagnostics.Process.Start(urlString);
...
this should launch the url in the default browser, no matter what platform you're on (WinXP, WinVista, Win7, Win8, etc)...
keep in mind that it expects a full url to recognize it as that and launch the browser...
Here is my xaml of the Panorama page item.
<controls:PanoramaItem x:Name="deeln" Header="Deelnemers" Style="{StaticResource subtitle}">
<!--Double line list with image placeholder and text wrapping-->
<ListBox Margin="12,0,-12,0" ItemsSource="{Binding ItemsDeelnemer}" x:Name="lbDeelnemer" SelectionChanged="lbDeelnemer_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled">
<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
<TextBlock Foreground="Black" TextWrapping="Wrap" Text="{Binding LineNr}" Style="{StaticResource PhoneTextExtraLargeStyle}" ></TextBlock>
<StackPanel Width="430" Height="100">
<TextBlock Foreground="Black" TextWrapping="Wrap" Text="{Binding LineNaamWielrenner1}" Style="{StaticResource PhoneTextExtraLargeStyle}" FontSize="35"></TextBlock>
<TextBlock Foreground="Black" TextWrapping="Wrap" Text="{Binding LineNaamWielrenner2}" Style="{StaticResource PhoneTextExtraLargeStyle}" FontSize="35"></TextBlock>
</StackPanel>
</StackPanel>
</ScrollViewer>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</controls:PanoramaItem>
Here is my code in the Panorama page.
private void lbDeelnemer_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
#region go to specific deelnemerinfo screen
// If selected index is -1 (no selection) do nothing
if (lbDeelnemer.SelectedIndex == -1)
return;
// Navigate to the new page
if (lbDeelnemer.SelectedIndex == 0)
{
NavigationService.Navigate(new Uri("/DeelnemerInfo.xaml", UriKind.Relative));
//NavigationService.Navigate(new Uri("/DeelnemerInfo.xaml?selectedItem=" + lbDeelnemer.SelectedIndex, UriKind.Relative));
}
// Reset selected index to -1 (no selection)
lbDeelnemer.SelectedIndex = -1;
#endregion
}
Here is my code from the non panorama page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//second try
string strItemIndex;
if (NavigationContext.QueryString.TryGetValue("goto", out strItemIndex))
PanoramaControl.DefaultItem = MyPanorama.Items[Convert.ToInt32(strItemIndex)];
base.OnNavigatedTo(e);
//first try
string selectedIndex = "";
if (NavigationContext.QueryString.TryGetValue("selectedItem", out selectedIndex))
{
int index = int.Parse(selectedIndex);
DataContext = App.ViewModel.ItemsDeelnemer[index];
}
}
My problem, I want to navigate like you do with a default databound application. You click on the first listitem and you go to a new page (non panorama).
It looks simple but i can't find it.
Try binding the tag attribute to the index/itemvalue
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<HyperlinkButton Tag="{Binding FileName}" Click="location_Click"/>
<TextBlock Text="{Binding DateCreated}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
navigate accordingly
private void location_Click(object sender, RoutedEventArgs e)
{
HyperlinkButton clicked = (HyperlinkButton)sender;
string uri = "/noteapp;component/ViewEdit.xaml?id=" + clicked.Tag;
NavigationService.Navigate(new Uri(uri, UriKind.Relative));
}
and on panaroma page use this something like this to retrieve the value
filename = NavigationContext.QueryString["id"];
var storage = IsolatedStorageFile.GetUserStoreForApplication();
using (var file = storage.OpenFile(filename, FileMode.Open))
I am developing an metro application (Windows 8) in c#, that allows; to drag the controls/elements (Button, text Boxes etc), and i am not sure how to do drag in metro app.
Please guide me,
Thanks in Advance
Here is complete source code. You can drag and drop any control onto canvas. Right now I am giving you example of button and textbox. For all other control the process is same.
XAML code
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<GridView
x:Name="GridViewControl"
AllowDrop="True"
Background="#FF2E5073"
CanDragItems="True"
DragItemsStarting="GridViewControl_DragItemsStarting"
SelectionMode="None"
>
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock
FontSize="14"
Text="{Binding}"
/>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel
Orientation="Vertical"
/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
<Canvas x:Name="Form"
AllowDrop="True"
Background="Black"
Drop="Form_Drop"
Grid.Column="1"
/>
</Grid>
C# code
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var ObserControl = new ObservableCollection<string>() { "Textbox", "Button" };
GridViewControl.ItemsSource = ObserControl;
}
private void Form_Drop(object sender, DragEventArgs e)
{
object sourceItem;
e.Data.Properties.TryGetValue("Item", out sourceItem);
double XPos = e.GetPosition(GridViewControl).X - 160;
double YPos = e.GetPosition(GridViewControl).Y;
if (sourceItem.ToString() == "Textbox")
{
var newTextbox = new TextBox();
newTextbox.Text = "Textbox";
newTextbox.SetValue(Canvas.LeftProperty, XPos);
newTextbox.SetValue(Canvas.TopProperty, YPos);
Form.Children.Add(newTextbox);
}
if (sourceItem.ToString() == "Button")
{
var newButton = new Button();
newButton.Content = "Button";
newButton.SetValue(Canvas.LeftProperty, XPos);
newButton.SetValue(Canvas.TopProperty, YPos);
Form.Children.Add(newButton);
}
}
private void GridViewControl_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
var item = e.Items.FirstOrDefault();
e.Data.Properties.Add("Item", item);
}
}