Load an image into a PictureBox on a different thread - winforms

I am trying to load a picture that is fetched on-demand from Google's Static Maps based against a (UK) Post Code.
Lets say I have a client and the clients has an address. One of the properties of client is PostCode. I have a form that loads clients. I feed the client ID to this form's constructor and then use LINQ 2 SQL to load all sorts of information including an address.
private void LoadBranchDetails() {
Text_Update_BI_Name.Text = Branch.BranchNumber;
Text_Update_BI_Manager.Text = String.Format("{0} {1}", Branch.PharmacyManager.FirstName, Branch.PharmacyManager.LastName);
DropDownList_Update_BI_Coordinator.SelectedValue = Branch.CoordinatorID;
DropDownList_Update_BI_ComputerSystem.SelectedValue = Branch.ComputerSystemID;
Text_Update_BI_Phone.Text = Branch.PhoneNumber;
Text_Update_BI_Fax.Text = Branch.FaxNumber;
Address BranchAddress = Branch.Contact.Addresses.FirstOrDefault();
Text_Update_AI_House.Text = BranchAddress.HouseNumber;
Text_Update_AI_Street.Text = BranchAddress.Street;
Text_Update_AI_Area.Text = BranchAddress.Area;
Text_Update_AI_Post.Text = BranchAddress.PostCode;
DropDownList_Update_AI_City.SelectedValue = BranchAddress.City.OID;
MaskedText_Update_OI_NoPharmacist.Value = Branch.NumberOfPharmacists;
MaskedText_Update_OI_NoDispensers.Value = Branch.NumberOfDispensers;
MaskedText_Update_OI_NoMonFri.Value = Branch.NumberOfItemsMondayToFriday;
MaskedText_Update_OI_NoSat.Value = Branch.NumberOfItemsSaturday;
MaskedText_Update_OI_NoSun.Value = Branch.NumberOfItemsSunday;
MaskedText_Update_OI_NoAddicts.Value = Branch.NumberOfAddicts;
MaskedText_Update_OI_NoSupervised.Value = Branch.Supervised;
MaskedText_Update_OI_NoUnsupervised.Value = Branch.Unsupervised;
Check_Update_OI_ConfRoom.Checked = Branch.ConsultationRoom;
try {
PictureGoogleMaps.Image = GoogleAddressInfo.FetchMapInfo(Text_Update_AI_Post.Text).GoogleStaticMap;
} catch (Exception) {
PictureGoogleMaps.Image = Resources.DefaultGoogleMap;
}
}
The line that loads the image into the PictureGoogleMaps causes a hang in UI as the ".GoogleStaticMap" property generates the Google static image when called.
Upon searching the internet, i found this helpful example:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Declare a list of URLs and their respective picture boxes
var items = new Dictionary<string, PictureBox>
{
{ "http://www.google.com/logos/spring09.gif", new PictureBox() { Top = 0, Width = 300, Height = 80 } },
{ "http://www.google.com/logos/stpatricks_d4gwinner_eo09.gif", new PictureBox() { Top = 100, Width = 300, Height = 80 } },
{ "http://www.google.com/logos/schiaparelli09.gif", new PictureBox() { Top = 200, Width = 300, Height = 80 } },
{ "http://www.google.com/logos/drseuss09.gif", new PictureBox() { Top = 300, Width = 300, Height = 80 } },
{ "http://www.google.com/logos/valentines09.gif", new PictureBox() { Top = 400, Width = 300, Height = 80 } },
{ "http://www.google.com/logos/unix1234567890.gif", new PictureBox() { Top = 500, Width = 300, Height = 80 } },
{ "http://www.google.com/logos/charlesdarwin_09.gif", new PictureBox() { Top = 600, Width = 300, Height = 80 } },
};
foreach (var item in items)
{
var worker = new BackgroundWorker();
worker.DoWork += (o, e) =>
{
// This function will be run on a background thread
// spawned from the thread pool.
using (var client = new WebClient())
{
var pair = (KeyValuePair<string, PictureBox>)e.Argument;
e.Result = new KeyValuePair<PictureBox, byte[]>(pair.Value, client.DownloadData(pair.Key));
}
};
worker.RunWorkerCompleted += (o, e) =>
{
// This function will be run on the main GUI thread
var pair = (KeyValuePair<PictureBox, byte[]>)e.Result;
using (var stream = new MemoryStream(pair.Value))
{
pair.Key.Image = new Bitmap(stream);
}
Controls.Add(pair.Key);
};
worker.RunWorkerAsync(item);
}
}
}
Now I just need to figure out how to remove the for loop and use this in my scenario. Any ideas?
The sample code comes from this link.
Thanks.

public partial class Form1 : Form
{
private BackgroundWorker imageLoader;
public Form1()
{
InitializeComponent();
this.imageLoader = new BackgroundWorker();
this.imageLoader.DoWork += HandleOnImageLoaderDoWork;
this.imageLoader.RunWorkerCompleted += HandleImageLoaderOnRunWorkerCompleted;
this.LoadUserDetails(1);
}
private void LoadUserDetails(Int32 userID)
{
this.imageLoader.RunWorkerAsync(userID.ToString());
// get the user details
// populate the UI controls with the data....
}
private void HandleImageLoaderOnRunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e)
{
this.pictureBox1.Image = (Image)e.Result;
}
private void HandleOnImageLoaderDoWork(Object sender, DoWorkEventArgs e)
{
// simulate a web request for an image;
Thread.Sleep(3000);
Image image = Image.FromFile(#"test.jpg");
e.Result = image;
}
}
Also make sure that you show some UI notification that a background operation is in process...something like a initial image (loading.gif) in the PictureBox.

Is it that hard to remove the foreach loop? You only need to load a single picture so remove the foreach loop and pass the url of the picture and the target picturebox to the backgroundworker.

Related

ImageComboBoxEdit selected value not settable

I'm trying to add an ImageComboBoxEdit control onto a UserControl within my WinForms application.
public ShortCutUserControl()
{
var imageCollection = new ImageCollection { ImageSize = new Size(48, 48) };
imageCollection.Images.Add(Image.FromFile(#"Keyboard\ctrl.ico"));
imageCollection.Images.Add(Image.FromFile(#"Keyboard\alt.ico"));
functionKeyImageComboBoxEdit.Properties.LargeImages = imageCollection;
ImageComboBoxItem ctrlItem = new ImageComboBoxItem
{
Description = "Ctrl",
ImageIndex = 0
};
ImageComboBoxItem altItem = new ImageComboBoxItem
{
Description = "Alt",
ImageIndex = 1
};
functionKeyImageComboBoxEdit.Properties.Items.Add(altItem);
functionKeyImageComboBoxEdit.Properties.Items.Add(ctrlItem);
}
When the control is loaded:
I can't change the currently either directly through code or in the UI.
functionKeyImageComboBoxEdit.SelectedIndex = 0;
I've tried attaching events to the functionKeyImageComboBoxEdit, but none of these seem to be fired/captured;
functionKeyImageComboBoxEdit.SelectedIndexChanged += FunctionKeyImageComboBoxEditOnSelectedIndexChanged;
private void FunctionKeyImageComboBoxEditOnSelectedIndexChanged(object sender, EventArgs eventArgs)
{
//throw new NotImplementedException();
}
What am I missing from my code? I've been looking at the DevExpress ImageComboBoxEdit Documentation but can't see any problem.
The cause of the issue is that you don't set values for ImageComboBoxItems. Do this like:
ImageComboBoxItem ctrlItem = new ImageComboBoxItem
{
Description = "Ctrl",
ImageIndex = 0,
Value = "Ctrl"
};
ImageComboBoxItem altItem = new ImageComboBoxItem
{
Description = "Alt",
ImageIndex = 1,
Value = "Alt"
};

Xamarin.Forms - Detect orientation & adjust page

I'd like to know the orientation of the device (Android, iOS & Windows Phone) at the time I'm building up my page. The page is having a grid with 3 columndefinitions and should have 5 columndefinitions as soon as the orientation got changed to landscape.
Grid grid = new Grid
{
HorizontalOptions = LayoutOptions.Fill,
VerticalOptions = LayoutOptions.Fill,
RowSpacing = 15,
ColumnSpacing = 15,
Padding = new Thickness(15),
ColumnDefinitions =
{
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
}
};
for (int i = 0; i < 12; i++)
{
Image img = new Image()
{
Source = "ButtonBlue.png"
};
//if(DependencyService.Get<IDeviceInfo>().IsPortraitOriented())
//{
grid.Children.Add(img, i % 3, i / 3);
//}
//else
//{
// grid.Children.Add(button, i % 5, i / 5);
//}
}
this.Content = new ScrollView
{
Orientation = ScrollOrientation.Vertical,
Content = grid
};
So here I added 12 images to test my code. The page is looking good in portrait-orientation and is having a lot of space between columns if the device is in landscape-orientation.
I'm also trying to use dependency injection to retrieve the information. The DependencyService is doing his job, but I don't have any success retrieving the orientation of the device...
In xamarin.forms, you can get notification from android part by using MessageCenter.
1.In Shared Project
public partial class MyPage : ContentPage
{
public MyPage ()
{
InitializeComponent ();
Stack = new StackLayout
{
Orientation = StackOrientation.Vertical,
};
Stack.Children.Add (new Button { Text = "one" });
Stack.Children.Add (new Button { Text = "two" });
Stack.Children.Add (new Button { Text = "three" });
Content = Stack;
MessagingCenter.Subscribe<MyPage> (this, "Vertical", (sender) =>
{
this.Stack.Orientation = StackOrientation.Vertical;
this.ForceLayout();
});
MessagingCenter.Subscribe<MyPage> (this, "Horizontal", (sender) =>
{
this.Stack.Orientation = StackOrientation.Horizontal;
this.ForceLayout();
});
}
public StackLayout Stack;
}
2.In Android Project
[Activity (Label = "XamFormOrientation.Android.Android", MainLauncher = true, ConfigurationChanges = global::Android.Content.PM.ConfigChanges.Orientation | global::Android.Content.PM.ConfigChanges.ScreenSize)]
public class MainActivity : AndroidActivity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
Xamarin.Forms.Forms.Init (this, bundle);
SetPage (App.GetMainPage ());
}
public override void OnConfigurationChanged (global::Android.Content.Res.Configuration newConfig)
{
base.OnConfigurationChanged (newConfig);
if (newConfig.Orientation == global::Android.Content.Res.Orientation.Portrait) {
MessagingCenter.Send<MyPage> (null, "Vertical");
} else if (newConfig.Orientation == global::Android.Content.Res.Orientation.Landscape) {
MessagingCenter.Send<MyPage> (null, "Horizontal");
}
}
}
I solved a similar problem and find it on great post which maybe helpfull for you (see hyperlink below).
In shortcut : Find out orientation by
Page.Width < Page.Height
and use this information in constructor of ContentPage (or other) when creating page
http://www.sellsbrothers.com/Posts/Details/13740

datagridview control continues update, gui flickers when scrolling window

Problem:
I have a Winform application with a form en on this form i have a databound DataGridView.
The datagridview is updated from the backend by updating the bind object continuesly using a timer to get the data every 10 seconds. In order to update the gui with this new data i call a RefreshDatabindings. (if i do not do this, the gui is nog updated, i am binding to a BindingList and the object implement the INotifyPropertyChanged)
When the form is big enough to show the whole datagridview at once everything is working wel. But when the form is not big enough to show the hole datagridview a scrollbar appears.
When i scroll to the right to see the rest of the datagridview i see the gui flickering (only the part that wasn't visible before scrolling). When i strech the form to make de gridview fitting again, everything is working wel (no flashing and flickering). the flickering only happens when i have to scroll.
I am lost, can please somebody help me :)?
I allready tryed the DoubleBuffered = true.
Thanks in advance!
BindingList<InstanceTableViewModel> viewModelList;
public Form1()
{
InitializeComponent();
DoubleBuffered = true;
functionParamList = new List<FunctionParameter>();
functionParamList.Add(new FunctionParameter { DeviceValue = 100, InstanceId = "1", Name = "A" });
functionParamList.Add(new FunctionParameter { DeviceValue = 200, InstanceId = "2", Name = "B" });
functionParamList.Add(new FunctionParameter { DeviceValue = 300, InstanceId = "3", Name = "C" });
viewModelList = CreateInstanceTableViewModelList();
dataGridView1.DataSource = viewModelList;
//Create timer
updateDataTimer = new System.Timers.Timer();
updateDataTimer.Interval = 500;
updateDataTimer.Elapsed += updateDataTimer_Elapsed;
updateDataTimer.Start();
}
private void updateDataTimer_Elapsed(object sender, ElapsedEventArgs e)
{
ThreadPool.QueueUserWorkItem(ReadDataThreadPoolMethod);
}
private void ReadDataThreadPoolMethod(object state)
{
Random random = new Random();
int randomNumber = random.Next(0, 100);
foreach (FunctionParameter param in functionParamList)
{
param.DeviceValue = Convert.ToInt64(randomNumber);
}
}
void functionParameter_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
var functionParameter = sender as FunctionParameter;
var propertyName = e.PropertyName;
var propertyValue = functionParameter.DeviceValue;
var parameterName = functionParameter.Name;
UpdateViewModel(functionParameter.InstanceId, propertyName, propertyValue, parameterName);
}
private void UpdateViewModel(string instanceId, string propertyName, long propertyValue, string parameterName)
{
var instanceViewModel = viewModelList.Single(x => x.InstanceId == instanceId && x.NameLabel == parameterName);
if (instanceViewModel != null)
{
instanceViewModel.ValueHex = Convert.ToUInt16(propertyValue);
}
ResetBindingsSource();
}
delegate void UpdateBindingsInvoker();
public void ResetBindingsSource()
{
if (!this.IsDisposed)
{
if (this.InvokeRequired)
{
this.Invoke(new UpdateBindingsInvoker(UpdateDataGrid));
}
else
{
UpdateDataGrid();
}
}
}
private void UpdateDataGrid()
{
dataGridView1.Refresh();
}
So here my solution:
You only uses the Forms DoubleBuffering, but the following code is an extension method to the DataGridview and successfully works (at my tests ;)
public static void DoubleBuffered(this DataGridView dgv, bool setting)
{
Type dgvType = dgv.GetType();
PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(dgv, setting, null);
}
I found this code right here at Codeprojct.
You can use it in this way:
YourDataGridView.DoubleBuffered(true);
I hope i could help you ^^

Why is the ListView with an ImageList very slow? (re: 1000+ thumbnails)

I'm trying to use a ListView component to show around 1,000 image thumbnails and I'm having some performance problems.
First I create an ImageList containing my 1,000 images. This is lightning fast and takes under a second.
However, once I assign the ImageList to my ListView, it takes around 10+ seconds.
Example:
ImageList _imgList = GetMyImageList(); // takes under 1 second
ListView _lstView = new ListView();
lstView.LargeImageList = _imgList; // takes 10+ seconds
Is there anything I can do to increase performance? My ImageList contains images that are already resized into thumbnail size (197x256 pixels) so that's not the problem... (and creating my ImageList only takes 1 second at the most).
Does the data in your list view change frequently? Do you load new image lists frequently?
I tried your scenario and got a few seconds of loading time (since I'm generating random images) but very fast refresh times when changing list view [View] modes as well as scrolling.
Here is the sample code. Try it out and let me know how it works.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApplication10
{
public partial class FormListView:
System.Windows.Forms.Form
{
public FormListView ()
{
string [] names = null;
this.InitializeComponent();
names = Enum.GetNames(typeof(View));
for (int i=0; i < names.Length; i++)
{
this.comboBox1.Items.Add(names [i]);
if (names [i] == this.ListView.View.ToString())
this.comboBox1.SelectedIndex = i;
}
}
private void comboBox1_SelectedIndexChanged (object sender, EventArgs e)
{
this.ListView.View = (View) Enum.Parse(typeof(View), this.comboBox1.SelectedItem.ToString());
this.ListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
}
private void ButtonLoadImages_Click (object sender, System.EventArgs e)
{
Image image;
Stopwatch watch;
this.Enabled = false;
this.Cursor = Cursors.WaitCursor;
this.ListView.SmallImageList = null;
this.ListView.LargeImageList = null;
this.ListView.StateImageList = null;
while (this.ImageList.Images.Count > 0)
{
this.ImageList.Images [0].Dispose();
this.ImageList.Images.RemoveAt(0);
}
this.ImageList.ImageSize = new System.Drawing.Size(256, 256);
watch = Stopwatch.StartNew();
for (int i=0; i < 1000; i++)
{
image = new Bitmap(this.ImageList.ImageSize.Width, this.ImageList.ImageSize.Height);
using (Graphics graphics = Graphics.FromImage(image))
{
graphics.Clear(Color.White);
graphics.DrawRectangle(Pens.Red, 10, 10, this.ImageList.ImageSize.Width - 20, this.ImageList.ImageSize.Height - 20);
graphics.DrawString(i.ToString(), this.Font, Brushes.Blue, 20, 20);
}
this.ImageList.Images.Add(image);
}
watch.Stop();
this.ListView.SmallImageList = this.ImageList;
this.ListView.LargeImageList = this.ImageList;
this.ListView.StateImageList = this.ImageList;
this.Text = watch.Elapsed.TotalSeconds.ToString();
this.Cursor = Cursors.Default;
this.Enabled = true;
}
private void ButtonLoadItems_Click (object sender, System.EventArgs e)
{
Stopwatch watch;
ListViewItem item;
this.Enabled = false;
this.Cursor = Cursors.WaitCursor;
this.ListView.Items.Clear();
this.ListView.Columns.Clear();
this.ListView.Columns.Add("Id", "Id");
this.ListView.Columns.Add("Name", "Name");
this.ListView.SmallImageList = null;
this.ListView.LargeImageList = null;
this.ListView.StateImageList = null;
this.ListView.BeginUpdate();
watch = Stopwatch.StartNew();
for (int i=0; i < 1000; i++)
{
item = new ListViewItem();
item.ImageIndex = i;
item.Text = i.ToString();
item.SubItems.Add("qwerty");
this.ListView.Items.Add(item);
}
this.ListView.EndUpdate();
this.ListView.SmallImageList = this.ImageList;
this.ListView.LargeImageList = this.ImageList;
this.ListView.StateImageList = this.ImageList;
this.ListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
watch.Stop();
this.Text = watch.Elapsed.TotalSeconds.ToString();
this.Cursor = Cursors.Default;
this.Enabled = true;
}
}
}

Windows phone 7.1 can I change font size on a shell tile?

I'm trying to display a tweet on the backside of a live tile, when I set it as BackContent it's way too big.... Is there any way to lower the font size?
EDIT:
Claus, Now i'm having trouble getting the tile to display and I can't get any info on why it's not working due to the nature of your ImageOpened call, I can't step through it with the debugger....
In my TileGenerator class, this works:
public static void GenerateTestTile(string strTweet, string strScreenName, string tileTitle)
{
// Define the tile's address. This is where you navigate, when the tile is clicked.
var address = "/MainPage.xaml?TileID=6";
// Check if a tile with the same address already exists
//var tile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString() == address);
var tile = ShellTile.ActiveTiles.First();
// Define our tile data.
var tileData = new StandardTileData
{
BackTitle = strScreenName,
BackContent = strTweet
};
// If the file already exists, update it.
if (tile != null)
{
tile.Update(tileData);
}
else
{
// Otherwise, create a new tile.
ShellTile.Create(new Uri(address, UriKind.Relative), tileData);
}
}
But this doesn't (exact method taken from your example), it doesn't do anything to the tile at all...
public static void GenerateExampleTile(string timeOfDay, string temperature, Uri cloudImagePath, string tileTitle)
{
// Setup the font style for our tile.
var fontFamily = new FontFamily("Segoe WP");
var fontForeground = new SolidColorBrush(Colors.White);
var tileSize = new Size(173, 173);
// Create a background rectagle for a custom colour background.
var backgroundRectangle = new Rectangle();
backgroundRectangle.Width = tileSize.Width;
backgroundRectangle.Height = tileSize.Height;
backgroundRectangle.Fill = new SolidColorBrush(Colors.Blue);
// Load our 'cloud' image.
var source = new BitmapImage(cloudImagePath);
source.CreateOptions = BitmapCreateOptions.None;
source.ImageOpened += (sender, e) => // This is important. The image can't be rendered before it's loaded.
{
// Create our image as a control, so it can be rendered to the WriteableBitmap.
var cloudImage = new Image();
cloudImage.Source = source;
cloudImage.Width = 100;
cloudImage.Height = 64;
// TextBlock for the time of the day.
TextBlock timeOfDayTextBlock = new TextBlock();
timeOfDayTextBlock.Text = timeOfDay;
timeOfDayTextBlock.FontSize = 20;
timeOfDayTextBlock.Foreground = fontForeground;
timeOfDayTextBlock.FontFamily = fontFamily;
// Temperature TextBlock.
TextBlock temperatureTextBlock = new TextBlock();
temperatureTextBlock.Text = temperature + '°';
temperatureTextBlock.FontSize = 30;
temperatureTextBlock.Foreground = fontForeground;
temperatureTextBlock.FontFamily = fontFamily;
// Define the filename for our tile. Take note that a tile image *must* be saved in /Shared/ShellContent
// or otherwise it won't display.
var tileImage = string.Format("/Shared/ShellContent/{0}.jpg", timeOfDay);
// Define the path to the isolatedstorage, so we can load our generated tile from there.
var isoStoreTileImage = string.Format("isostore:{0}", tileImage);
// Open the ISF store,
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
// Create our bitmap, in our selected dimension.
var bitmap = new WriteableBitmap((int)tileSize.Width, (int)tileSize.Height);
// Render our background. Remember the renders are in the same order as XAML,
// so whatever is rendered first, is rendered behind the next element.
bitmap.Render(backgroundRectangle, new TranslateTransform());
// Render our cloud image
bitmap.Render(cloudImage, new TranslateTransform()
{
X = 8, // Left margin offset.
Y = 54 // Top margin offset.
});
// Render the temperature text.
bitmap.Render(temperatureTextBlock, new TranslateTransform()
{
X = 124,
Y = 63
});
// Render the time of the day text.
bitmap.Render(timeOfDayTextBlock, new TranslateTransform()
{
X = 12,
Y = 6
});
// Create a stream to store our file in.
var stream = store.CreateFile(tileImage);
// Invalidate the bitmap to make it actually render.
bitmap.Invalidate();
// Save it to our stream.
bitmap.SaveJpeg(stream, 173, 173, 0, 100);
// Close the stream, and by that saving the file to the ISF.
stream.Close();
}
// Define the tile's address. This is where you navigate, when the tile is clicked.
var address = "/MainPage.xaml?TileID=" + timeOfDay;
// Check if a tile with the same address already exists
var tile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString() == address);
// Define our tile data.
var tileData = new StandardTileData
{
BackgroundImage = new Uri(isoStoreTileImage, UriKind.Absolute),
Title = tileTitle,
};
// If the file already exists, update it.
if (tile != null)
{
tile.Update(tileData);
}
else
{
// Otherwise, create a new tile.
ShellTile.Create(new Uri(address, UriKind.Relative), tileData);
}
};
}
Both methods are being called in this way....
public class ScheduledAgent : ScheduledTaskAgent
{
...
/// <summary>
/// Agent that runs a scheduled task
/// </summary>
/// <param name="task">
/// The invoked task
/// </param>
/// <remarks>
/// This method is called when a periodic or resource intensive task is invoked
/// </remarks>
protected override void OnInvoke(ScheduledTask task)
{
LoadWatchList();
}
//WATCH LIST
private void LoadWatchList()
{
if (HasConnectivity)
{
GetWatchListTweetsFromTwitter(CurrentWatchListID);
}
}
public void GetWatchListTweetsFromTwitter(int list_id)
{
WebClient wcWatchListTimeline = new WebClient();
wcWatchListTimeline.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wcWatchListTimeline_DownloadStringCompleted);
wcWatchListTimeline.DownloadStringAsync(new System.Uri("https://api.twitter.com/1/lists/statuses.xml?per_page=1&list_id=" + list_id));
}
void wcWatchListTimeline_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
String strTweet = "content";
String strScreenName = "title";
if (e.Error != null)
{
strScreenName = "error";
strTweet = e.Error.Message;
}
else
{
XElement tweet = XElement.Parse(e.Result);
Tweet thisTweet = GetTweet(tweet);
if (thisTweet != null)
{
strTweet = thisTweet.text;
strScreenName = thisTweet.screen_name;
}
}
// TAKEN FROM EXAMPLE FOR TESTING - NOT WORKING
string timeOfday = "morning";
string temperature = "99";
string location = "San Antonio";
Uri cloudImagePath = new Uri("Images/tweetEmpty.png", UriKind.Relative);
Deployment.Current.Dispatcher.BeginInvoke(() => TileGenerator.GenerateExampleTile(timeOfday, temperature, cloudImagePath, "mainTile"));
//WORKING
//Deployment.Current.Dispatcher.BeginInvoke(() => TileGenerator.GenerateTile(strTweet, strScreenName, "mainTile"));
NotifyComplete();
}
protected Tweet GetTweet(XElement Xdata)
{
List<Tweet> listTweets = (from tweet in Xdata.Descendants("status")
select new Tweet
{
screen_name = tweet.Element("user").Element("screen_name").Value,
text = tweet.Element("text").Value
}).ToList<Tweet>();
if (listTweets.Count > 0)
{
return listTweets[0];
}
else
{
return null;
}
}
}
Only by creating a custom image, and using that as the background for the tile.
Updated: How To: Live Tile with Scheduled Agent

Resources