We’ll be adding a new xaml page with a textBox for the tweet and an application bar with a save and cancel button.
Right click on the “Views” folder in the solution. Select “Add” then “New Item”. Pick the “Windows Phone Portrait Page” template and give the page a name, I’ll name the page “TweetPage.xaml”. Hit the “Add” button when done.
In the TweetPage.xaml file, change the “ApplicationTitle” to “Twitt” and the “PageTitle to “new tweet”. Also remove the applicatoin bar code that is at the bottom. I”m going to show you how to add it via code. Your file should look like this:
<phone:PhoneApplicationPageLet’s now add a button on our MainPage.xaml to open up this new page. Open “MainPage.xaml” and find the third panorama item that we added in part 2. It should look like this:
x:Class="Twitt.Views.TweetPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True"> <!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="Twitt" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="new tweet" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel> <!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
</Grid>
</phone:PhoneApplicationPage>
<!--Panorama item three-->Add a new button and I’ll add names to each button and change the Click EventHandler names to match:
<controls:PanoramaItem Header="settings">
<StackPanel>
<Button Content="Account Settings" Click="Button_Click"/>
</StackPanel>
</controls:PanoramaItem>
<!--Panorama item three-->We’ll need to create the new event handler for our new button in the MainPage.xaml.cs file:
<controls:PanoramaItem Header="settings">
<StackPanel>
<Button x:Name="SettingsButton" Content="Account Settings" Click="SettingsButtonClick"/>
<Button x:Name="TweetButton" Content="New Tweet" Click="TweetButtonClick"/>
</StackPanel>
</controls:PanoramaItem>
private void SettingsButtonClick(object sender, RoutedEventArgs e)Compile and run the app to ensure that pressing the new button opens our “new tweet” page:. Let’s now add the TextBox and a couple TextBlock labels to our new “TweetPage.xaml” where the user will enter their tweet. We’ll add the new code inside the “ContentPanel” “Grid” node.
{
NavigationService.Navigate(new Uri("/Views/TwitterAuthPage.xaml", UriKind.Relative));
} private void TweetButtonClick(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/Views/TweetPage.xaml", UriKind.Relative));
}
<!--ContentPanel - place additional content here-->I’ve added one TextBlock for a title above the control to tell the user to “tap to edit”. I’ve also added a seond TextBlock to update the number of characters remaining, since tweets can only hold a maximum of 140 characters.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBlock x:Name="TitleTextBlock" HorizontalAlignment="Center" FontSize="{StaticResource PhoneFontSizeLarge}" Text="Twitter Message (tap to edit)" TextWrapping="Wrap"/>
<TextBlock x:Name="CharactersCountTextBlock" HorizontalAlignment="Center" Text="140 characters remaining"/>
<TextBox x:Name="TweetTextBox" Height="250" HorizontalAlignment="Stretch" TextWrapping="Wrap" TextChanged="TweetTextBoxTextChanged" KeyUp="MessageTextBoxKeyUp" IsTabStop="true" InputScope="Text"/>
</StackPanel>
</Grid>
I’ve set the “InputScope” property to “Text” on the TextBox control. Setting to “Text” will show the user suggested words as they type them on top of the keypad. I’ve also added the “MessageTextboxKeyUp” event handler. I want to dismiss the keypad if the user hit the “Enter” key. For this to work you also need to set “IsTabStop” property to “true”.
I’ve also hooked up the “TextChanged” Event Handler so that as users type I can update the characters left TextBlock that I added. Here’s what the code behind looks like:
namespace Twitt.ViewsI’ve made a helper method called “UpdateRemainingCharacters” which I also call from the constructor to set the text as well as being called from “TweetTextBoxTextChanged”.
{
public partial class TweetPage : PhoneApplicationPage
{
public TweetPage()
{
InitializeComponent(); UpdateRemainingCharacters();
} private void UpdateRemainingCharacters()
{
CharactersCountTextBlock.Text = String.Format("{0} characters remaining", 140 - TweetTextBox.Text.Length);
} private void TweetTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
UpdateRemainingCharacters();
} private void MessageTextBoxKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
Focus();
}
}
}
}
Running the app, the “new tweet” page should now look like this:
If you select the TextBox and start typing you should see the keypad and suggested words I previously mentioned:
Next, we’ll add the application bar to the bottom for our “tweet” and cancel buttons. In the TweetPage.xaml.cs, add the following new “CreateApplicationBar” method. I enclosed it in “#region” to keep my code cleaner.
public TweetPage()
{
InitializeComponent();
CreateApplicationBar(); UpdateRemainingCharacters();
} #region ApplicationBar private void CreateApplicationBar()
{
ApplicationBar = new ApplicationBar { IsMenuEnabled = true, IsVisible = true, Opacity = .9 }; var save = new ApplicationBarIconButton(new Uri("/Resources/Images/check.png", UriKind.Relative));
save.Text = "tweet";
save.Click += SaveClick;
save.IsEnabled = false; var cancel = new ApplicationBarIconButton(new Uri("/Resources/Images/cancel.png", UriKind.Relative));
cancel.Text = "cancel";
cancel.Click += CancelClick; ApplicationBar.Buttons.Add(save);
ApplicationBar.Buttons.Add(cancel);
} private void CancelClick(object sender, EventArgs e)
{
if (NavigationService.CanGoBack)
NavigationService.GoBack();
}
private void SaveClick(object sender, EventArgs e)
{
} #endregion In “CreateApplicaitonBar” I add two buttons, the first one is for sending the tweet to Twitter. I set the “IsEnabled” property to “false.” We need to check if the user has validated their account before we enable this button. Notice I’m using two images “Resources/Images/check.png” and also “Resources/Images/cancel.png”. We’re going to need to go get these two images.
Application icons are installed with the development tools and located here: C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Icons The two icons we need are located at \Icons\dark\appbar.cancel.rest.png and \Icons\dark\appbar.check.rest.png. We need to add these two icons to our “Resources/Images” folder. Right click on “Images”, select “Add” and then “Existing Items” and add the two files. Let’s rename them to “check.png” and “cancel.png”. Right click on each one and select “Rename”. Try running the app now, and openeing the “new tweet” page, you should see this: The icons are not showing up. You need to set each icon as a “content” type instead of the default “resource”. To do this, right click on each image file and select “Properties” and set the “Build Action” to “Content”.
Now run the app and the page should now look like this:
Try the cancel button. It should navigate back.
We now need to check if the user has been authenticated with Twitter and if so, enable the “Tweet” icon on the application bar. I’m going to load the saved settings and check if the “AccessToken” and “AccessTokenSecret” exist, if so enable the first button:
public partial class TweetPage : PhoneApplicationPageNow run the app. If the “Tweet” button is still disabled on the “new tweet” page, go back to the main page and ensure you hit “Account Settings” to authenticate your Twitter account. Note: every time you close the emulator down the Isolated Storage is wiped out. You’ll have to re-authenticate every time you reload the emulator. However, if you just exit the app and don’t close the emulator you won’t have to do this.
{
private TwitterAccess _twitterSettings; public TweetPage()
{
InitializeComponent();
CreateApplicationBar(); UpdateRemainingCharacters();
} protected override void OnNavigatedTo(NavigationEventArgs e)
{
_twitterSettings = Helper.LoadSetting<TwitterAccess>(Constants.TwitterAccess);
if (_twitterSettings == null) return; ((ApplicationBarIconButton)ApplicationBar.Buttons[0]).IsEnabled = !String.IsNullOrEmpty(_twitterSettings.AccessToken) && !String.IsNullOrEmpty(_twitterSettings.AccessTokenSecret);
}
…
Once you’re authenticated you should get this screen. The “Tweet” button however still won’t do anything, we’ll tackle that next.
When we hit the “Tweet” button, we’re going to want a progress bar to show something is going on. In the TweetPage.xaml above the “TitlePanel” I’ve added a ProgressBar. I’ve set the “Visibility” property to “Collapsed” so it is off by default. For performance reasons you should also set “IsIndeterminate” to “False” when it’s not visible,
<!--TitlePanel contains the name of the application and page title-->I’m now going to create a “TwitterHelper” class to wrap all of our calls to Twitter. Under the “Common” folder create a new class (Right click folder, “Add” –> “Class”:
<ProgressBar x:Name="ProgressBar" VerticalAlignment="Top" IsIndeterminate="False" Visibility="Collapsed"/>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="Twitt" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="new tweet" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
Here’s the code for our “TwitterHelper” class:
using System;
using System.Net;
using System.Windows;
using Hammock;
using Hammock.Authentication.OAuth;
using Hammock.Web; namespace Twitt.Common
{
public class TwitterHelper
{
private readonly TwitterAccess _twitterSettings;
private readonly bool _authorized;
private readonly OAuthCredentials _credentials;
private readonly RestClient _client;
public event EventHandler TweetCompletedEvent;
public event EventHandler ErrorEvent; public TwitterHelper(TwitterAccess settings)
{
_twitterSettings = settings; if (_twitterSettings == null || String.IsNullOrEmpty(_twitterSettings.AccessToken) ||
String.IsNullOrEmpty(_twitterSettings.AccessTokenSecret))
{
return;
} _authorized = true; _credentials = new OAuthCredentials
{
Type = OAuthType.ProtectedResource,
SignatureMethod = OAuthSignatureMethod.HmacSha1,
ParameterHandling = OAuthParameterHandling.HttpAuthorizationHeader,
ConsumerKey = TwitterSettings.ConsumerKey,
ConsumerSecret = TwitterSettings.ConsumerKeySecret,
Token = _twitterSettings.AccessToken,
TokenSecret = _twitterSettings.AccessTokenSecret,
Version = TwitterSettings.OAuthVersion,
}; _client = new RestClient
{
Authority = "http://api.twitter.com",
HasElevatedPermissions = true
};
} public void NewTweet(string tweetText)
{
if (!_authorized)
{
if (ErrorEvent != null)
ErrorEvent(this, EventArgs.Empty);
return;
} var request = new RestRequest
{
Credentials = _credentials,
Path = "/statuses/update.json",
Method = WebMethod.Post
}; request.AddParameter("status", tweetText); _client.BeginRequest(request, new RestCallback(NewTweetCompleted));
} private void NewTweetCompleted(RestRequest request, RestResponse response, object userstate)
{
// We want to ensure we are running on our thread UI
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
if (response.StatusCode == HttpStatusCode.OK)
{
if (TweetCompletedEvent != null)
TweetCompletedEvent(this, EventArgs.Empty);
}
else
{
if (ErrorEvent != null)
ErrorEvent(this, EventArgs.Empty);
}
});
}
}
} I’ll walk through this code now: In the constructor, we take in the TwitterAccess object. This was already loading in our “TweetPage” so we will pass it through. This object contains the User Tokens. If the tokens were passed in successfully we set an “_authorized” member variable to true. This will be used to ensure we’ll have stored credentials when we make calls to the class methods. The constructor also sets up the “_credentials” and “_client” objects as they are needed for all authorized calls to Twitter. Next is the “NewTweet” method. This is the method we’ll call when the user presses the “Tweet” button. It will first check that we are authorized and then make the call. Last in this file, is the “NewTweetCompleted” Callback method, which is called when the Twitter call is completed. We need to check if the call was successful or not. I set up two different Events to fire back, one for a successful call and one for a failed call. All we have left is the “TweetPage.xaml.cs” code that makes this call and hooks up the two event handlers. Here is the code:
private void SaveClick(object sender, EventArgs e)The first thing this method does is turns on the ProgressBar by setting the “Visibility” property to “Visible” and also turns on the “IsIndeterminate” property to “true”. We then setup the two callback event handlers (one for success and one for failed calls). Both will turn the progressbar off. Failed calls will also display an error message. Successful calls will navigate back to the previous page. That’s it! We can now tweet from the app. Next Part of this series I’ll show how to get friend statuses, mentions, direct messages and favorites. You can find the source code for part 3 here: http://twitt.codeplex.com/ Sam
{
PostTweet();
} … private void PostTweet()
{
if (String.IsNullOrEmpty(TweetTextBox.Text))
return; ProgressBar.Visibility = Visibility.Visible;
ProgressBar.IsIndeterminate = true; var twitter = new TwitterHelper(_twitterSettings); // Successful event handler, navigate back if successful
twitter.TweetCompletedEvent += (sender, e) =>
{
ProgressBar.Visibility = Visibility.Collapsed;
ProgressBar.IsIndeterminate = false;
if (NavigationService.CanGoBack)
NavigationService.GoBack();
}; // Failed event handler, show error
twitter.ErrorEvent += (sender, e) =>
{
ProgressBar.Visibility = Visibility.Collapsed;
ProgressBar.IsIndeterminate = false;
MessageBox.Show("There was an error connecting to Twitter");
}; twitter.NewTweet(TweetTextBox.Text);
}
Great series, complete with all the little details of a professional app. The link for source code takes me to my Live home page after a redirect.
ReplyDeletevery interesting and well explained. a side note: when I tried to download the code I found myself on my live page, could not reach the url you provided.
ReplyDeleteBrilliant article. Thanks so much for doing this. And... like others here the download link is not working. Is there any chance you might be able to fix that? Very much appreciated :-)
ReplyDeleteA little digging around... and the following link works for me (not sure why ?client=wnf works)
ReplyDeletehttp://cid-229b74769854b9a9.office.live.com/self.aspx/Twitt/Twitt%20Part%203.zip?client=wnf
I'm about to post part 4, I think i'll look at using CodePlex for the code instead of windows live.
ReplyDeleteThe source code can now be found at: http://twitt.codeplex.com/
ReplyDeleteVery helpful post! Thanks.
ReplyDeleteIt would also be helpful to know how to post an update with an image. I've been looking at this documentation
https://dev.twitter.com/docs/api/1/post/statuses/update_with_media
and your code, but I can't figure it out. I have to say I'm not familiarized with REST. So any guidelinens in this way would be great!
Thanks for such interesting posts!
hi,
ReplyDeletei have aproblem.I am not able to send the tweets as the button is disabled.I ve followed each step but still couldnt get the check button enabled.Can u pls help me out as soon as possible..
Thanks in advance
hi,
ReplyDeleteI have downloaded your code and executed it on Emulator, Authentication part is ok, but unable to post the tweet and also unable to get the messages. All time their is Error.
Can you please help me out of this??
Hi mind_freak,
ReplyDeleteTwitter retired some of their older 1.0 APIs, it seems the xml versions are no longer working.
I wrote this 2 years ago with those. It's not a hard change however just use the json equivalent, so for posting a tweet use this:
var request = new RestRequest
{
Credentials = _credentials,
Path = "/statuses/update.json",
Method = WebMethod.Post
};
Hope that helps.
Sam
I tried the above and it still getting error, since the json output is different than xml.
ReplyDeleteAfter changing the path to .json, iam getting the error at
var xmlElement = XElement.Parse(response.Content);
Can you please help me to solve it, Since i am trying a twitter app for wp7.
I am getting Forbidden Error. Can you provide a new example using with API 1.1 for both windows phone 7 and 8? Please??? I need your help for windows phone 7.
ReplyDeleteThe latest Android and iOS app stores in 2018
ReplyDeleteHello friends
Are you using the old app store? Want to change your store? You are finding? Shop for the best quality app, free app for everyone in the world. Visit this site for additional settings by following the instructions here: https://iplaystoredownloadfree.com/
Here are the stores you can refer to:
- Google Play windows phone
- How to fix Play Store errors
- Play Store for PC
Hope my store will bring a new look to the phone world. Wish you have the best app store for your mobile device, thanks!
Legend Online Benzeri Oyunlar
ReplyDeleteMafia 2 Benzeri Oyunlar
Simcity Benzeri Oyunlar
Papers Please Benzeri Oyunlar
Phasmophobia Benzeri Oyunlar
JBK