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
Related
I'm following the instructions here;
https://www.syntaxismyui.com/xamarin-forms-masterdetail-page-navigation-recipe/
The navigation bar icon is placed too far to the right by default. Is there a way to center it on the navigation bar? The hamburger menu icon is also pushed far to the right.
EDIT: I added a picture for an example of what I have. Funny thing, in another app the icon is all the way to the left.
EDIT:
Here's the code:
public class RootPage : MasterDetailPage
{
MenuPage menuPage;
public RootPage()
{
menuPage = new MenuPage();
menuPage.Menu.ItemSelected += (sender, e) => NavigateTo(e.SelectedItem as MenuItem);
Master = menuPage;
NavigationPage page = new NavigationPage(new Home());
page.BarBackgroundColor = Color.FromHex("#56198E");
Detail = page;
}
void NavigateTo(MenuItem menu)
{
if (menu == null)
return;
Page displayPage = (Page)Activator.CreateInstance(menu.TargetType);
NavigationPage page = new NavigationPage(displayPage);
page.BarBackgroundColor = Color.FromHex("#56198E");
Detail = page;
menuPage.Menu.SelectedItem = null;
IsPresented = false;
}
}
public class MenuPage : ContentPage
{
public ListView Menu { get; set; }
public MenuPage()
{
Icon = "settings.png";
Title = "menu"; // The Title property must be set.
BackgroundColor = Color.FromHex("#56198E");
Menu = new MenuListView();
var menuLabel = new ContentView
{
Padding = new Thickness(10, 36, 0, 5),
Content = new Label
{
TextColor = Color.FromHex("#C8C8C8"),
Text = "MENU",
}
};
var layout = new StackLayout
{
Spacing = 0,
VerticalOptions = LayoutOptions.FillAndExpand
};
layout.Children.Add(menuLabel);
layout.Children.Add(Menu);
Content = layout;
}
}
public class MenuListView : ListView
{
public MenuListView()
{
List<MenuItem> data = new MenuListData();
ItemsSource = data;
VerticalOptions = LayoutOptions.FillAndExpand;
BackgroundColor = Color.Transparent;
// SeparatorVisibility = SeparatorVisibility.None;
var cell = new DataTemplate(typeof(MenuCell));
cell.SetBinding(MenuCell.TextProperty, "Title");
cell.SetBinding(MenuCell.ImageSourceProperty, "IconSource");
ItemTemplate = cell;
}
}
public class MenuListData : List<MenuItem>
{
public MenuListData()
{
this.Add(new MenuItem()
{
Title = " Home",
IconSource = "Home.png",
TargetType = typeof(Home)
});
this.Add(new MenuItem()
{
Title = " Register for Classes",
IconSource = "Calendar.png",
TargetType = typeof(Register)
});
this.Add(new MenuItem()
{
Title = " Search Instructors",
IconSource = "ContactsSearch.png",
TargetType = typeof(SearchInstructors)
});
}
}
public class MenuItem
{
public string Title { get; set; }
public string IconSource { get; set; }
public Type TargetType { get; set; }
}
I would recommend trying different icon sizes. I was having some issues myself when the image was too large. In my tests I was originally using a 144x144 image and it worked correctly most of the time. When I attempted a 700x700 pixel image it was dead center and I would lose my title.
Screen Resolution - 768x1280
App Icon
144x144 - Slightly away from flush next to the Menu Icon
700x700 - Center
Menu Icon -44x44 (and always flush to the left)
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 ^^
I am having trouble adding a custom zoom-able an pan-able picture box control to a tabcontrol.tabpage dynamically at runtime. I have tried a lot and was wondering if any of you smart fellas might have some advice for a poor noob like myself... here is some code...
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace TAQTv4
{
public class ZoomPanPicBox : ScrollableControl
{
private Image _image;
//Double buffer the control
public ZoomPanPicBox()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
this.AutoScroll = true;
this.Image = null;
this.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
this.Zoom = 1f;
}
//New
[Category("Appearance"), Description("The image to be displayed")]
public Image Image
{
get { return _image; }
set
{
_image = value;
UpdateScaleFactor();
Invalidate();
}
}
private float _zoom = 1f;
[Category("Appearance"), Description("The zoom factor. Less than 1 to reduce. More than 1 to magnify.")]
public float Zoom
{
get { return _zoom; }
set
{
if (value < 0 || value < 1E-05)
{
value = 1E-05f;
}
_zoom = value;
UpdateScaleFactor();
Invalidate();
}
}
private void UpdateScaleFactor()
{
if (_image == null)
{
this.AutoScrollMargin = this.Size;
}
else
{
this.AutoScrollMinSize = new Size(Convert.ToInt32(this._image.Width * _zoom + 0.5f), Convert.ToInt32(this._image.Height * _zoom + 0.5f));
}
}
//UpdateScaleFactor
private InterpolationMode _interpolationMode = InterpolationMode.High;
[Category("Appearance"), Description("The interpolation mode used to smooth the drawing")]
public InterpolationMode InterpolationMode
{
get { return _interpolationMode; }
set { _interpolationMode = value; }
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
}
//OnPaintBackground
protected override void OnPaint(PaintEventArgs e)
{
//if no image, don't bother. I tried check for IsNothing(_image) but this test wasn't detecting a no-image.
if (_image == null)
{
base.OnPaintBackground(e);
return;
}
//Added because the first test sometimes failed
try
{
int H = _image.Height;
//Throws an exception if image is nothing.
}
catch (Exception ex)
{
base.OnPaintBackground(e);
return;
}
//Set up a zoom matrix
Matrix mx = new Matrix(_zoom, 0, 0, _zoom, 0, 0);
mx.Translate(this.AutoScrollPosition.X / _zoom, this.AutoScrollPosition.Y / _zoom);
e.Graphics.Transform = mx;
e.Graphics.InterpolationMode = _interpolationMode;
e.Graphics.DrawImage(_image, new Rectangle(0, 0, this._image.Width, this._image.Height), 0, 0, _image.Width, _image.Height, GraphicsUnit.Pixel);
base.OnPaint(e);
}
//OnPaint
}
}
//ZoomPicBox
Now this seems to work fine while using the designer... but when trying to add images and controls at runtime the tabs instantiate fine but the zoomPicBox control does nothing so it would seem... This is how I am using it....
public void loadImagesToTabControl()
{
int i = 0;
foreach (Bitmap bitmap in intDwg.getBitmaps())
{
//ToDo add pic boxes and tabs and bitmaps to tabcontrol1
TAQTv4.ZoomPanPicBox picBox = new TAQTv4.ZoomPanPicBox();
picBox.Image = bitmap;
picBox.Anchor = AnchorStyles.Top;
picBox.Anchor = AnchorStyles.Bottom;
picBox.Anchor = AnchorStyles.Left;
picBox.Anchor = AnchorStyles.Right;
picBox.AutoScroll = true;
picBox.CausesValidation = true;
picBox.Visible = true;
picBox.Zoom = 1;
picBox.BackgroundImageLayout = ImageLayout.Tile;
picBox.Location = new System.Drawing.Point(0, 0);
picBox.TabStop = true;
picBox.Enabled = true;
picBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
picBox.CreateControl();
string title = "Pg " + (tabControl1.TabCount + 1).ToString();
TabPage myTabPage = new TabPage(title);
tabControl1.TabPages.Add(myTabPage);
tabControl1.TabPages[i].Controls.Add(picBox);
i++;
/* Possible pictureBox Implementation...
string title = "Pg " + (tabControl1.TabCount + 1).ToString();
TabPage myTabPage = new TabPage(title);
tabControl1.TabPages.Add(myTabPage);
PictureBox picbox = new PictureBox();
picbox.Anchor = AnchorStyles.Top;
picbox.Anchor = AnchorStyles.Bottom;
picbox.Anchor = AnchorStyles.Left;
picbox.Anchor = AnchorStyles.Right;
picbox.Image = bitmap;
picbox.Height = 800;
picbox.Width = 1300;
tabControl1.TabPages[i].Controls.Add(picbox);
i++;
*/
}
}
}
And as a last note... the pictureBox implementation worked fine as well so I know I am pulling my images from disk fine in the deserialization method of my intDwg class. Any thoughts would be much appreciated! Thanks in advance!
UPDATE:
I got the control to load pictures by setting backgroundimage to bitmap instead of picBox.Image.... FRUSTRATING .... but it seems that the way I have it set up the image is not anchored correctly ... trying to improve this and work it out now... any tips and tricks would be just awesome! Thanks!
UPDATE:
A Screen shot... as you can see the tab pages load correctly and one for each bitmap in my collection, yet the custom zoomPanPicBox control does not seem to want to display! See Bellow:
ahh .... seems I don't have rep to post pics.... ... alright how about...
https://www.dropbox.com/s/ogj5jlcce831n3p/scrst.png?v=0mcns
...
UPDATE AGAIN GOT IT THANKS All was missing setting the size as you had mentioned using the following: picBox.SetBounds(0, 0, 300, 300);
:D:D:D:D:D:D:)
Also, instead of using a counter:
TabPage myTabPage = new TabPage(title);
tabControl1.TabPages.Add(myTabPage);
tabControl1.TabPages[i].Controls.Add(picBox);
i++;
Just use your "myTabPage" reference:
TabPage myTabPage = new TabPage(title);
myTabPage.Controls.Add(picBox);
tabControl1.TabPages.Add(myTabPage);
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
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.