WP Manager for XING

WP Manager for XING

WP Manager for XING

One of the reasons why I’ve been so quiet on this blog is that I’ve been busy working on another Windows Phone app… After the “failed” attempt (details about this adventure will come soon in a separate post) with My Delicious (a Windows Phone manager for Delicious bookmarks), I’ve decided to take another shot.

While I’m a long time user of LinkedIn, some time last year I’ve got an invitation from somebody to join XING… you may wonder what is XING? XING is a professional social network, very similar to LinkedIn, but very popular in Germany. They have an official Windows Phone app, which when I got it was free, but in the meanwhile got a price of €2.99. As this was the only option in the marketplace, I’ve decided to take a shot and write my own app.

Why?

  • I’ve never worked before with an API which is using OAuth for authentication
  • XING has a rather impressive API which can lead to complex apps
  • I wanted to refresh my Windows Phone development skills

After a longer than expected development period (developing in the spare time has it’s ups and downs and you’re not always keen to write more code after a long day in the office), about a month ago I’ve released to the MarketPlace “WP Manager for XING”.

The app is FREE and currently allows:

  • view your profile
  • update your status
  • view the news feed
  • like and share activities
  • view your contacts, visitors and people recommended for you
  • manage your XING messages
  • pin a contact to your home screen for quick access
  • save a XING contact to your phone’s contact list

In few days I hope I’ll be able to push a new update for the app in the MarketPlace which will fix some known bugs and also provide some additional features…

The application can be downloaded from the MarketPlace using this link: http://www.windowsphone.com/en-us/store/app/wp-manager-for-xing/37e790ef-4bff-4c32-a2a3-dc41c2ba2e86

Below are some screenshots take from the app…

news feed

news feed

news feed activity

news feed activity

contacts

contacts

more options

more options

user profile

user profile

messages view

messages view

recommendations

recommendations

share

share

Feedback and suggestions are welcomed so don’t hesitate to contact me!

Using (and customizing) the AutoCompleteBox for Windows Phone

This is my first article on Windows Phone 7 development and I will focus on a subject that was useful in one of my recent projects: using the an autocomplete box in a Windows Phone 7 application.

By default, the Windows Phone SDK doesn’t include an AutoCompleteBox control for use, but as probably many people already know, the Silverlight Toolkit library released on CodePlex contains such a control designed for the phone.

In order to demo the usage of the AutoCompleteBox control we’ll create a very simple application which will allow us to select our favourite cities from a predefined list. I am using Microsoft Visual Studio 2010 Express for Windows Phone.

Once you downloaded the latest Windows Phone Silverlight Toolkit – November 2011 (7.1 SDK) and installed it, you will  need to add a reference to the Microsoft.Phone.Controls.Toolkit.dll assembly in your project.

add_reference

To use the AutoCompleteBox control in your XAML, you will need to edit the XAML source and add the toolkit namespace as shown before:

namespace

After this step you are ready to use the AutoCompleteBox in your page. The AutoCompleteBox is a rather simple control to use, looking like a regular TextBox, but as the user starts typing into it, it displays a suggestions drop-down list based on the matches found. For the AutoCompleteBox to offer the suggestions based on what’s being typed we need to make sure that we set the ItemsSource property of the control which takes an IEnumerable collection.

For the simplest use of the AutoCompleteBox, all you have to do once you performed the steps above is to create an AutoCompleteBox control in your XAML as shown below:

autocomplete_xaml

and then assign the ItemsSource property to a collection (I’ve done it in code behind, but you can also use binding in your XAML):

autocomplete_codebehind

That’s it! Now you can run your application and test it… If you would be typing the character s, you should be seeing something like this:

app1

If you want to get the value from the AutoCompleteBox, you can check the Text property of the AutoCompleteBox control.

In a real world application it makes sense that you may want to set the Text property to some previously stored value and then allow the user to modify it if necessary.

So, after setting the ItemsSource of the AutoCompleteBox to the list of cities, add an extra line that will also set the Text property to Suceava (value that exists in our list):

cities.Text = “Suceava”;

If you run the  application again, you notice you have a problem:

app2

The AutoCompleteBox control has the suggestions drop-down list opened… I don’t want that by default and I guess most people don’t want this behaviour as well. So let’s fix it.

We need to handle 3 simple events exposed by the AutoCompleteBox:

events

All the events are rather simple and their names are very clear: the GetFocus and LostFocus are triggered when the control gets and loses the focus, while the DropDownOpening event is triggered just before the opening of the suggestion drop-down allowing us to stop the suggestion if needed.

The GetFocus and LostFocus will set a boolean variable to true or false to allow us to know if the control is focused or not. In the DropDownOpening event we will use this boolean value and we will not allow the drop-down list to open if the control is not focused – just the scenario we have above. To stop the drop-down from opening we need to cancel the event. Here is the code:

events2

Try running the application again once you implemented the events above. The application should behave as expected: the control has by default the value “Suceava” and the drop-down list is not opened by default.

What we’ve done so far is a very simple scenario of AutoCompleteBox usage. In lots of cases it could be enough, in others not.

Imagine you want to allow your users to input multiple cities in the same AutoCompleteBox control, each city separated by a comma and for each city you want to help your user by providing him help (suggestions) based on what he’s typing.

If you run the application now and type a comma after your initial selection and then start typing the first letter of another city, you will not get any suggestions as the list provided to the ItemsSource property doesn’t contain any string that will match your entire text value.

To finish this demo, we’ll try to modify the default behaviour of the AutoCompleteBox and customize it to allow us to cover the previous scenario.

To implement this, we’ll need to:

  • use one variable to remember the previously typed cities
  • handle the TextChanged and SelectionChanged events of the AutoCompleteBox. The TextChanged event has the same use as for a TextBox control, while the SelectionChangedevent is triggered when the selection in the suggestion drop-down control is changed.
  • we need also to implement a custom search method that will be used by the TextFilter property of the AutoCompleteBox

We will use the TextChanged event to store in the new variable the previous cities that the user types, in the SelectionChanged we will make sure to append the newly selected city to the previously typed cities.

The custom filtering method will make sure that we use only what is after a comma as search term. Also, this method will make sure to filter out cities that we already typed.

So, to get to the coding part, we need to attach some more events to the AutoCompleteBox:

events3

The custom filter method is rather simple and looks like this:

textfilter

The TextChanged and SelectionChanged events are also simple:

changed_events

If you will run the application again you will see that the same AutoCompleteBox allows us to input multiple cities, separated by comma and for each new city we get suggestions as we type.

app3

Hope that this demo will be useful to others and hope the explanations were clear enough. The AutoCompleteBox is a very useful control in lots of cases and with a bit of customization it can be quite powerful.

A very useful article that I read when I first started to use the control is AutoCompleteBox for WP7 in depth which provides plenty of valuable information about the various properties and events exposed by the control. If you need to learn more about the control, check it as it’s a very good resource.

The full project for this demo can be downloaded here – feel free to take it, run it and play with it.

Also, any comments or suggestions related to this demo are welcomed, so drop me a line in the comments if you have something to say.

Happy coding!

Adding a “watermark” to an image in ASP.NET

Currently I am working on a personal project in ASP.NET and one of the tasks is to store images in a MySQL database and later retrieve and show them to the users.

Just for demo purpose, the MySQL table structure is very simple:

db_structure

First step of my task was actually storing the images in the MySQL table and for that I used Entity Framework in order to simplify the data handling.

For adding a new image to the database I created one very simple ASP.NET page:

ASP.NET
  1. <asp:FileUpload ID="fileUploadControl" runat="server" />
  2. <asp:Button ID="UploadButton" runat="server" Text="Upload" OnClick="UploadButton_Click" /><br />
  3. <asp:Label ID="StatusLabel" runat="server" Text="" />

and the code behind for uploading the image and displaying the image details in case of success, or the error in case of any issue is:

C#
  1. protected void UploadButton_Click(object sender, EventArgs e)
  2. {
  3. if (fileUploadControl.HasFile)
  4. {
  5. try
  6. {
  7. ImagesDbEntities2 ent = new ImagesDbEntities2();
  8. images img = new images();
  9. img.name = fileUploadControl.FileName;
  10. img.data = fileUploadControl.FileBytes;
  11. img.type = fileUploadControl.PostedFile.ContentType;
  12. ent.AddToimages(img);
  13. ent.SaveChanges();
  14. StatusLabel.ForeColor = Color.Black;
  15. StringBuilder sb = new StringBuilder();
  16. sb.Append("File Name: " + fileUploadControl.FileName + "<br />");
  17. sb.Append("File Size: " + fileUploadControl.PostedFile.ContentLength + " bytes <br />");
  18. sb.Append("File Type: " + fileUploadControl.PostedFile.ContentType + "");
  19. StatusLabel.Text = sb.ToString();
  20. }
  21. catch (Exception ex)
  22. {
  23. StatusLabel.ForeColor = Color.Red;
  24. StatusLabel.Text = "EXCEPTION: " + ex;
  25. }
  26. }
  27. else
  28. {
  29. StatusLabel.ForeColor = Color.Red;
  30. StatusLabel.Text = "Please select a file to upload!";
  31. }
  32. }

The simple code above allows us to store images in the MySQL table, so next task is to retrieve an image and display it on a web page. For this I created a simple ASP.NET webpage which based on the image ID I pass in the query string it returns the image with that ID from the database. There is only code-behind written for this task and I have 2 implementations:

  1. writing some simple text on top of the image and center it
  2. using a custom image with transparent background and center it on top of the image

Most of the implementation for both ways of adding the watermark to the image is the same and consists in retrieving the table entry based on the ID we pass in the URL query string, creating a MemoryStream object based on the bytes stored on the data field and then create an Image object from the MemoryStream created previously. Also in order to write a text on top of the image or display the watermark image over the initial image we need to create a Graphics object and call the DrawString or DrawImage methods.

So, here is the code to display a text over the image retrieved from the database:

C#
  1. public partial class GetImage : System.Web.UI.Page
  2. {
  3. MemoryStream ms = null;
  4.  
  5. protected void Page_Load(object sender, EventArgs e)
  6. {
  7. if (!IsPostBack)
  8. {
  9. string id = Request.QueryString["id"];
  10. if (!string.IsNullOrEmpty(id))
  11. {
  12. ImagesDbEntities2 ent = new ImagesDbEntities2();
  13. long imgID = Convert.ToInt64(id);
  14. var image = (from img in ent.images where img.id == imgID select img).FirstOrDefault();
  15. if (image != null)
  16. {
  17. MemoryStream ms = new MemoryStream(image.data);
  18. System.Drawing.Image memImage = System.Drawing.Image.FromStream(ms);
  19. Graphics g = Graphics.FromImage(memImage);
  20. Font f = new Font("Arial", 12, FontStyle.Bold);
  21. SolidBrush brush = new SolidBrush(Color.Red);
  22. SizeF stringDimens = g.MeasureString("AndreiC - 2010", f, 300);
  23. if (stringDimens.Width < memImage.Width && stringDimens.Height < memImage.Height)
  24. {
  25. g.DrawString("AndreiC - 2010", f, brush,
  26. (memImage.Width - stringDimens.Width) / 2,
  27. (memImage.Height - stringDimens.Height) / 2);
  28. }
  29.  
  30. Response.ContentType = "image/Jpeg";
  31. memImage.Save(Response.OutputStream, ImageFormat.Jpeg);
  32.  
  33. // Clean-up
  34. ms.Dispose();
  35. memImage.Dispose();
  36. g.Dispose();
  37. }
  38. }
  39. }
  40. }
  41. }

If we want to display the image with ID=1 from the database, all we have to do is add the following HTML code in the page:

HTML
  1. <img src="GetImage.aspx?id=1" />

The result is:

text_test

In case you want to add an image as watermark over your database stored image, you can use the following code:

C#
  1. public partial class GetImage : System.Web.UI.Page
  2. {
  3. MemoryStream ms = null;
  4.  
  5. protected void Page_Load(object sender, EventArgs e)
  6. {
  7. if (!IsPostBack)
  8. {
  9. string id = Request.QueryString["id"];
  10. if (!string.IsNullOrEmpty(id))
  11. {
  12. ImagesDbEntities2 ent = new ImagesDbEntities2();
  13. long imgID = Convert.ToInt64(id);
  14. var image = (from img in ent.images where img.id == imgID select img).FirstOrDefault();
  15. if (image != null)
  16. {
  17. System.Drawing.Image watermark = System.Drawing.Image.FromFile(
  18. Server.MapPath("Images/andreic_watermark.png"));
  19. MemoryStream ms = new MemoryStream(image.data);
  20. System.Drawing.Image memImage = System.Drawing.Image.FromStream(ms);
  21. Graphics g = Graphics.FromImage(memImage);
  22.  
  23. // draw watermark only if image is larger than watermark image
  24. if (watermark.Height < memImage.Height && watermark.Width < memImage.Width)
  25. {
  26. g.DrawImage(watermark,
  27. (memImage.Width - watermark.Width) / 2,
  28. (memImage.Height - watermark.Height) / 2);
  29. }
  30. Response.ContentType = "image/Jpeg";
  31. memImage.Save(Response.OutputStream, ImageFormat.Jpeg);
  32. // Clean-up
  33. ms.Dispose();
  34. watermark.Dispose();
  35. memImage.Dispose();
  36. g.Dispose();
  37. }
  38. }
  39. }
  40. }
  41. }

For this implementation I had to create one additional PNG image with transparent background and I placed it in the project inside a folder named Images.

The HTML code to show the image stays the same and the result is:

img_watermark_test

Hope this helps!

MySQL Membership and Roles Providers for ASP.NET

Recently I started working on a personal project and before diving into some real coding, I decided to go ahead and refresh some of my ASP.NET skills and knowledge as I didn’t do any serious ASP.NET development in more than 1.5 years. As most probably I will host the project on GoDaddy and will start with Economy plan until some upgrades will be necessary I am planning to use MySQL as data repository as they offer 10 MySQL databases of 1GB each- enough space for what I need at the beginning.

Since my project will need to support authentication of users and different roles within the application, I started refreshing my knowledge on the Membership and Roles providers. As my choice for database is MySQL I was afraid I will have to write custom providers to work with membership and roles stored in a MySQL database. Fortunately, I found out there is a much easier way of doing this thanks to the latest MySQL Connector for .NET.

Here are the steps I followed in order to set-up Membership and Roles providers using the MySQL .NET Connector.

  • download and install the latest MySQL .NET Connector. I am using version 6.3.4
  • create a new Web Project in Visual Studio and after add references to MySql.Data and MySql.Web
  • the MySQL .NET Connector will modify your machine.config file after installation and will add new entries in the membership, roleManager and profile providers. You will need to locate the machine.config file under the following location: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG and edit it. You will need to add one extra attribute to the MySql Membership Provider defined in there: autogenerateschema=“true”.  The autogenerateschema=“true” attribute will cause MySQL Connector/NET to silently create, or upgrade, the schema on the database server, to contain the required tables for storing membership information. After this change the MySql Membership Provider in the  machine.config file should look like this:
XML
  1. <add name="MySQLMembershipProvider"
  2. autogenerateschema="true"
  3. connectionStringName="LocalMySqlServer"
  4. ... />
  • one other change made in the machine.config file by the MySQL .NET Connector is in the connectionsStrings section where a new connection for MySql is added:
XML
  1. <add name="LocalMySqlServer" connectionString="" />

We will need to override this connection string in our web.config in order to specify the details on the MySQL database used to create the tables structure that supports the membership and roles providers. Because the membership and roles providers defined in the machine.config file use the already defined MySql connection string, we will need to remove it and then add it again. Our connectionStrings section in web.config file should look like:

XML
  1. <connectionStrings>
  2. <remove name="LocalMySqlServer"/>
  3. <add name="LocalMySqlServer"
  4. connectionString="Datasource=localhost;Database=db_name;uid=user;pwd=password;"
  5. providerName="MySql.Data.MySqlClient"/>
  6. </connectionStrings>
  • although this step can be done from the Website Administration Tool, I prefer to do it directly in the web.config file as it’s very simple. In order to support forms authentication, locate the authentication section in your web.config file and change the mode attribute from Windows to Forms:
XML
  1. <authentication mode="Forms"/>
  • open the Website Administration Tool and switch to the Provider tab and then select the Select a different provider for each feature (advanced) link to set the providers. You should see the MySQLMembershipProvider and MySQLRoleProvider listed. I selected both of them as I want both membership and roles to be stored in my MySQL database. After you close the Administration Tool, your web.config file should be get modified and you’ll notice that under the system.web section the following lines where added:
XML
  1. <roleManager defaultProvider="MySQLRoleProvider"/>
  2. <membership defaultProvider="MySQLMembershipProvider"/>
  • save your solution and build it. If you check your database you should see the tables structure generated:

tables

  • once you finish this step and want to go ahead and use the MySQL Membership and Roles providers in your code you should modify your web.config file once again. I replaced the above mentioned entries for role and membership sections with the entries found in the machine.config file:
XML
  1. <roleManager enabled="true" defaultProvider="MySQLRoleProvider">
  2. <providers>
  3. <clear/>
  4. <add name="MySQLRoleProvider" type="MySql.Web.Security.MySQLRoleProvider"
  5. connectionStringName="LocalMySqlServer" applicationName="MysqlTest" />
  6. </providers>
  7. </roleManager>
  8.  
  9. <membership defaultProvider="MySQLMembershipProvider">
  10. <providers>
  11. <clear/>
  12. <add name="MySQLMembershipProvider" type="MySql.Web.Security.MySQLMembershipProvider"
  13. connectionStringName="LocalMySqlServer" enablePasswordRetrieval="false"
  14. enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="MysqlTest"
  15. requiresUniqueEmail="false" passwordFormat="Clear" maxInvalidPasswordAttempts="5"
  16. minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1"
  17. passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
  18. </providers>
  19. </membership>

Of course you can customize the attributes of the role and membership providers as you wish. I changed the applicationName attribute to be able to differentiate later between application entries in the tables.

  • from this moment you should be able to use Login related controls in your application. Just for testing purposes I added one CreateUserWizard control which works fine without writing  any code, and then I used one Login control for which I implemented the OnAuthenticate event as follows:
C#
  1. protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
  2. {
  3. bool authenticated = false;
  4. authenticated = Membership.ValidateUser(Login1.UserName, Login1.Password);
  5. e.Authenticated = authenticated;
  6.  
  7. if(authenticated)
  8. {
  9. FormsAuthentication.SetAuthCookie(Login1.UserName, true);
  10. Response.Redirect("Secret.aspx");
  11. }
  12. else
  13. {
  14. // do some error handling
  15. }
  16. }

In order to implement this I followed as references:

  1. http://dev.mysql.com/doc/refman/5.1/en/connector-net-tutorials-asp-roles.html
  2. http://blog.nolanbailey.com/2008/03/08/mysql-aspnet-membership-and-role-provider/194

Hope this comes useful for others as well!

Implementing a transparent row selection in a DataGridView control

During a recent project I was involved in, I had to implement a transparent row selection for the DataGridView control in a Winforms C# 2.0 application. This meant that instead of getting the usual dark blue color (SystemColors.Highlight) for each cell of the selected row to paint only a certain cell as dark blue and a dark blue border around the visible part of the row, the rest of the cells having to keep their already set colors.

The first thing that we need to take care in the grid view control in case we want to have a row selection is to set the SelectionMode property of the grid control to FullRowSelect. This will make sure that each time we select one cell, the entire row will be selected.

full_row_select 

Once we complete this step we should start working on the actual “transparent” selection. In order to customize the look of the cells we need to implement the CellFormatting event of the DataGridView control and to change the way the cell looks when it’s selected we can customize two properties: SelectionBackColor (to change the background color of the cell in the selected state) and SelectionForeColor (to handle the color of the text in the cell in the selected state).

In order to have the first cell selected normally and the rest of the cells in the row to have the “transparent” selection look I used the following code for the CellFormatting event:

Code Snippet
  1. private void musicGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
  2.         {
  3.             // for the first cell paint paint the background as highlight and text as white in case of selection
  4.             if (e.ColumnIndex == 0)
  5.             {
  6.                 e.CellStyle.SelectionBackColor = SystemColors.Highlight;
  7.                 e.CellStyle.SelectionForeColor = Color.White;
  8.             }
  9.             else
  10.             {
  11.                 e.CellStyle.SelectionBackColor = e.CellStyle.BackColor;
  12.                 e.CellStyle.SelectionForeColor = e.CellStyle.ForeColor;
  13.             }
  14.         }

 

If we run the application after this step well get something like the following screenshot:

selection_no_border

This looks fine, but it’s not enough – this looks like we would have cell level selection allowed only for the first column. This would look much better if we would paint a border around the selected row, to make it clear which row is selected and what type of selection mode we have. To achieve this I implemented the RowPostPaint event and used the following piece of code to draw a rectangle around my selected row:

Code Snippet
  1. private void musicGridView_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
  2.         {
  3.             var dgv = (DataGridView)sender;
  4.             // run this piece of code only for the selected row
  5.             if (dgv.Rows[e.RowIndex].Selected)
  6.             {
  7.                 int width = musicGridView.Width;
  8.                 Rectangle r = dgv.GetRowDisplayRectangle(e.RowIndex, false);
  9.                 var rect = new Rectangle(r.X, r.Y, width – 1, r.Height – 1);
  10.                 // draw the border around the selected row using the highlight color and using a border width of 2
  11.                 ControlPaint.DrawBorder(e.Graphics, rect,
  12.                     SystemColors.Highlight, 2, ButtonBorderStyle.Solid,
  13.                     SystemColors.Highlight, 2, ButtonBorderStyle.Solid,
  14.                     SystemColors.Highlight, 2, ButtonBorderStyle.Solid,
  15.                     SystemColors.Highlight, 2, ButtonBorderStyle.Solid);
  16.             }
  17.         }

 

Once we implement this event for our grid view we’ll reach the result we wanted:

transparent_selection

This way of selecting a row in a DataGridView control can be very useful in case in the CellFormatting event we implement some logic to paint certain cell in some specific way based on some business logic. For example a red background for a cell in case of an error for that grid entry and so on… Such formatting would not be visible in case of the row beiong selected and we having left the default row selection implementation.

Implementing such a selection is not a very difficult task, but if you are not very familiar with the DataGridView control it can be tricky to know where and how to implement this. Hope this short article will be useful for other people as well.