| Neil Bamber's profileFriendMap - Made in Expr...BlogLists | Help |
|
8/2/2006 Help! Part 2.Yesterday I talked about how create a CHM file but I didn’t mention how to include into your project and have it display when a user wants it. I’ve toyed around with Visual C# and this is the method that I’ve used. Now all I need to do is write some help and everyone will be happy.
To include the file in your project load Visual C# and load your project, then find the Solution Explorer. Right click on the solution and mouse over the Add menu and then select Existing Item this displays a standard dialog box you should be familiar with. Navigate to where your Compiled HTML help file is and select it. The file should now appear in the project along with your forms and code. Right click on the file and choose properties, then set the Copy to Output Directory property to Copy Always or Copy if Newer. This allows you to easily reference the help file with out worrying about file paths later on.
To get your help file displaying in your application is a relatively easy process once you know how. I wasn’t too sure until I saw the HelpProvider control. Drag the control on to your form and rename it to something meaningful if you feel inclined. Now we need to change the HelpNamespace property of the HelpProvider to the name of the CHM that was added to the project, in my case FriendMapHelp.chm.
Once the HelpProvider is on your form and has been set up we need to create some events that will utilise it, for example the user clicking Index in the Help menu. In the Click event that has just been created add the following line.
System.Windows.Forms.Help.ShowHelp(this, hlpFriendMap.HelpNamespace);
Where this is the parent control (in my case, the main form of my application), hlpFriendMap is the HelpProvider control that was added and it’s property HelpNamespace is the name of this Compiled HTML help file. After compiling and running the application and clicking on the help button you should be shown your help file.
Now all I have to do is write the help file for my application. 8/1/2006 Help!So like most of the other active contestants I’m currently implementing a help file for my application. As said writing help is the most boring part for a developer (for me at least) and to be honest, I don’t think developers can write help files. Well, a developer who has been working on the project from day one anyway. We just know how to do things, we know what to do and what not to do so trying to explain it to someone who hasn’t is difficult because something you take for granted is something a user might not know.
But I digress. Until tonight I had no idea how I’d implement a help file for my application. The help file wouldn’t be too large, but I’d the user to be able to see a list of topics and search for keywords. These requirements, unless I wanted to spend a significant time writing code, limited me to using the compiled HTML format or CHM. How can I implement CHM help in my application though?
After a bit of searching I discovered that Microsoft have an application available for the creation of CHM files, this application (aptly named HTML Help) can be found here. HTML Help looks very Windows 98, I’m somewhat surprised Microsoft haven’t implemented updated version within Visual Studio, maybe they have in the fuller versions? I’m not sure.
To create a CHM file a user must choose the New option from the File menu and select Project from the dialog box that is displayed. This will begin a wizard running the user through creating a new project, allowing them to convert from previous help files and add existing files to the project. Once the project has been created (assuming no content has been added) the user must create the content so the help file is actually helpful.
To add content click on the Contents tab and follow the prompts to create a new contents file. This is what the user will see when they first load the help file. There won’t be anything in there yet because it has just been created. To add some content add a HTML file to the project from the File, New menu and enter a heading for the page. Now content can be added to this html file, a user can create as many files as they want. Once the user is done adding content to the help file HTML files can be added to the project by clicking the Insert a page link on the left of the window. When finished adding files the user can go to the File menu and choose Compile…. This will result in a compiled CHM that can be viewed by the user, either directly through Windows or from your application.
So there is a very elementary crash course on how to create a CHM file for use in your application. Hopefully a few people will find this step by step process useful. I’ll look into how to actually get the CHM displaying from within an application tomorrow and blog about that, but for now it’s time for bed. 7/31/2006 Lines.
Linked above is the work I accomplished today, I added code to determine and draw the strength of a relationship link. This formula takes into account the friend rating, the years the friend has been known, the importance and rating of the last event and the days since the last event. I then multiplied that figure (it’s always between 0 and 1) by 7 and there you go, weighted lines. Why 7? Because that’s what looked the best on the map. :)
Another cool .NET feature I learned about today (and appreciate even more after having been doing a rather date math heavy PHP app at work recently.) is the TimeSpan class used in conjunction with the DateTime.Subtract() method. The TimeSpan class in my application is used to get the number of days since the last event and today. However you can also get information such as hours, seconds, milliseconds etcetera.
Something that was a little harder than I though it would be was creating a context menu for my Friends DataGridView. I assumed that I’d be able to access the RowIndex through a menu item click, however I couldn’t. I also figured that the row I had clicked on would become selected. I had a look through the DataGridView events (is there an object with properties and events than a DGV?) and found the RowContextMenuStripNeeded event, by firing this event I’m able to get the RowIndex, I store the RowIndex in the ContextMenu’s tag for easy access. I also select the DataGridView row in this method with the line, dgvFriends.Rows[e.RowIndex].Selected = true;
Tomorrow I hope to work on the circle weighting (and possibly colouring, I’m not sure if I’ll implement that yet.) and add a ContextMenu for the events DataGridView. Other than using it as a shortcut to load friends and events I’m not sure what else I can put in the ContextMenus. It feels wrong only having one option to choose from in a ContextMenu. 7/30/2006 Another Lazy Sunday.I think it’s safe to say that Sundays are not my best developing days. I didn’t get a whole lot done today and only spent about four hours on my application. I started the day with good intentions but then it went down hill from there. On the upside Ninety Nine Nights for the 360 looks fun and I finished Cloning Clyde.
Application wise I worked out a few more bugs and shined up a few areas of the application. One problem I was having that I mentioned last week (I think) was my contacts owner drawn ListBox not drawing anything. I spent ages one day last week trying to figure out why the DrawItem and MeasureItem events were not firing. I looked through my code, multiple times over, I checked that the events were actually set up (unlike last time this happened), they were and I checked the designer code and everything seemed fine. I wanted to get this fixed today so I sat down and had a look again and ended up finding out the problem. For some reason this line had been removed from the designer code, this.Controls.Add(this.lstContacts);. So the ListBox was never added, except the control displayed as a ListBox on the form in the designer and when the application ran. In the end I was happy it was fixed but still annoyed it took so long to fix.
Oh well. Today I ended up fixing all but one of the bugs on my list. Tomorrow should be more productive and I’ll try and get that bug fixed. Depending on how quickly I’m able to fix it I may also start adding a few more small features just to make things a little more hectic. 7/29/2006 Bug Fixing.After a fair bit of “research” last night I sat down this morning to begin working though my TODO and BUG list, grabbing at the low hanging fruit first. I’ve fixed 25 bugs today so far, but they are all of the relatively easy ones and a few of the more medium difficulty ones. Regardless of how hard the bugs have been to fix the time I’ve spent today is well reflected in the applications quality.
One of the areas of my application I wanted to fix today was the ComboBoxes. I’ve used ComboBoxes fairly extensively through out my application and they were generally filled with entries from the database. This was all well and good except that users could still put their own entry in and that would cause problems. This problem was something that I thought would be easy to fix and I never got around to finding out how to make a ComboBox read only. Well, for a change, I was right and making a ComboBox read only is as easy as setting it’s DropDownStyle property to DropDownList.
In fixing these bugs I’ve come across an issue with the ToolStrip smart tag, when I remove buttons from a ToolStrip using the Edit Items… link that are between other buttons, the spacing of the buttons stays the same in the designer, as if the deleted buttons were still there. However when the application runs the buttons are aligned properly. The buttons stay the same even after rebuilding the project.
In other news that developers may be interested in Microsoft has announced Sandcastle, a documentation compiler http://blogs.msdn.com/sandcastle/. While I wouldn’t find a use for it on a small project such as this (especially as there is little to no documentation) on a larger project it would be great. It’s also great to see Microsoft releasing more free tools for developers.
I’m pleased I decide against implementing a the FriendMap control as a planar graph. It would have caused me a significant amount of stress trying to get it working in such a short period of time and would have prevented me from fixing existing issues, although it would have looked a lot nicer than the current implementation. Tomorrow I plan on climbing the tree a bit and taking a swing at the medium and high hanging fruit. That’s usually sweeter right? 7/28/2006 9 Days Left.Since I was not the mood for programming when I got home last night I went through my application and made a list of everything that needs doing before the 6th of August. Unfortunately the list is a lot bigger than I’d like it to be so some things will have to be cut and others made not as fully featured as I’d like them to be. The list has about 20 entries, pretty much 50/50 between TODOs and BUGs, of course I’m looking forward to the TODOs introducing more bugs. My weekend is looking somewhat busy with activities tonight and tomorrow night, so I’ll have to make the best of Saturday during the day and Sunday, only 9 more days until the project is due. I’m glad it’s due on a Sunday giving me a weekend to work on it.
In other news I discovered (via the CodeProject forums) that Microsoft have the MSDN library available as a stand alone download, it’s pretty huge if you get the whole package but useful to have. I often find my self developing with out Internet access and I want to know something about the object I’m working on in more detail than Intellisense provides, so having the MSDN library available on my computer will fix that problem.
The library can downloaded from http://www.microsoft.com/downloads/details.aspx?FamilyId=373930CB-A3D7-4EA5-B421-DD6818DC7C41&displaylang=en 7/27/2006 Escaping SQL.I’ve been terribly busy with a few real life things since I got back so I’ve not had much time to do any work on my application. I’m slowly progressing bit by bit though. For the little time I programmed today I fixed some bugs and added some code to escape the SQL queries the user can add input to.
Escaping SQL in .NET is apparently done automatically when using ADO.NET correctly by using the following code.
SqlCommand command = new SqlCommand("SELECT * from people where name = " + txtFilter.Text, dbConn)But I’m not using ADO.NET correctly so that’s crazy talk. The way I’m doing it is escaping the user input using the Regex.Replace() function, as so.
private string EscapeText(string text) { return Regex.Replace(text, "'", @"''"); }
Again, I really need to learn ADO.NET properly. :)
Tomorrow will be another busy day where I won’t have any time to work on my program. I’ll have to spend the majority of this weekend fixing bugs and getting my application ready for submission. It’s getting close. 7/25/2006 Back.Unfortunately I’m back in the land of work after a nice break. I read up on graph theory and I’ve decided that trying to implement a planar graph in such a small window of time for my application is a bad idea and that the time would be better spent adding polish and fixing as many bugs as possible. Once the application has been submitted I’ll implement the planar graph, just so I can say I’ve done it.
I did a little bit of work while I was away (aside from reading up graph theory) but nothing too major. I finally added the ability for some one to create a new owner; it was just something I never got around to doing until now. I also changed a few areas that were still using DataSets and therefore not updating when rows were added to the database. Hopefully I don’t lose too many points for that.
I’ll get back into it proper tomorrow and start work on fixing a few more issues (my contacts list box has stopped drawing itself for some reason) but for now I’m still on Holiday. 7/23/2006 Holiday!I fixed my problem yesterday of the DataSet not being updated, well more worked around it. After trying everything I could think I eventually gave up and tried working around it. In the end I selected what I wanted from the table, then set the properties of the combo box to display what I selected. I’ll paste the code below to show you what I mean.
private void FillEventCategory() { DatabaseInfo dbInfo = new DatabaseInfo(); SqlCommandBuilder sqlCb; string query = "select event_category_id, name from event_category"; SqlDataAdapter dataAdapter = new SqlDataAdapter(query, dbInfo.ConnectionString); sqlCb = new SqlCommandBuilder(dataAdapter);
DataSet dataSet = new DataSet(); dataAdapter.Fill(dataSet); DataTable dataTable = dataSet.Tables[0];
cmbEventCategory.DataSource = dataTable; cmbEventCategory.DisplayMember = "name"; cmbEventCategory.ValueMember = "event_category_id"; }
This code is called from the forms OnLoad event and as you can see selects fields from the event category table and sets the DataSource of the combo box to the results, and then sets the DisplayMember and ValueMember properties. I know this isn’t the correct way but it’s the way that ended up working for me. I’m looking forward to getting the ADO.NET Programming book from Manning Publications so I can see what the correct way use ADO.NET is.
With that I’m off for two days to read up on graph theory and how I can use it in my application. I think I’ve updated my blog every day this month so hopefully no one will miss me :P 7/22/2006 Saturday!I got very little done today; I caught up with a friend after being behind him on the freeway coming home this morning. Lunch turned into mixing which then turned into dinner and then playing xbox for a while, oh well, I’m on holiday. I did get a little bit of coding done but not too much, I fixed a plainly obvious bug that was displaying the category id rather than the text.
One of the other bugs I wanted to fix today wasn’t fixed, my noob ADO.NET code came to bite me in the ass as I thought it would. When adding events or friends the categories and such are selected from the data sets. Since my code updates the database directly the data set stays the same. I’ve tried a few different things (DataSet.Table.Rows.Add(newRow), updating the dataset from the database) but couldn’t get it working; I’ll have to look into it a bit more closely in the few hours I’ve got tomorrow. 7/21/2006 Uh oh.Unfortunately drawing the lines in a neat way isn’t as easy as I was hoping it would be, I’ve had a look around and deduced that my problem is related to Graph Theory. Graph Theory is the drawing of points and the lines from those points, in my FriendMap application each friend is a point, and the link between them can be represented by line. In my applications case I want an undirected, planar graph. An algorithm that produces no intersections is better than one that does produce intersecting lines, however not all graphs can be drawn in such a way. Wikipedia has more information about Graph Theory here. Looks like I’ll be taking some light reading along on my two day holiday.
Of course simply reading about Graph Theory isn’t going to solve my problem. I’ve already thought about ways I can display the map in a neater fashion and after I’ve read up a little more I’ll try and implement it. What I’m imagining is the owner point being moved into the centre of map and links being drawn from there. The same principle would be followed for friends who are linked to other friends. So if I’m friends with Friend A and Friend A knows Friends B, C, and D. The owner point (me) would be in the centre of the screen, linked to Friend A would be centre of Friends B, C and D. What I’m a little unclear on at the moment is how to store where people are located or even if I need too after they’ve been drawn. As I said, I’ll do more reading while I’m away.
I’ll try spending a few days after I get back implementing a cleaner graph and if I can’t do that I’ll have to submit with the graph I have now. Since I won’t be implementing the new graph tomorrow I’ll spend the day going through the application and fixing bugs. There are a fair few small bugs that I’ve left behind in the pursuit of getting my application close to finished. 7/20/2006 Cloning Neil.
I didn’t get too much done today due to a longer day at work and using an hour of my development time playing the new Xbox Live Arcade game Cloning Clyde (I could certainly use some clones.). I accomplished what I set out to do though which is good, the drawing of the lines didn’t take as long as I thought it would.
Linked above is the result of tonight’s work. Relating to yesterdays post I figured out why the MessageBox informing the user the map had run out of space was being continually displayed. It was something pretty silly and due to my inexperience with Windows.Forms. Drawing the MessageBox over the control invalidated the panel, causing the panel to be redrawn, redrawing the panel in the same size results in the same message being displayed, which invalidates the panel. Hooray for infinite loops! I didn’t realise the panel was being redrawn when the MessageBox was displayed. To solve the issue I simply wrote the error on the Panel using the DrawString method, the error is red so it stands out.
Once I had that problem fixed it was time to start drawing the links between friends. This ended up being easier than I thought it would be and just involves using the function DrawLine from the Graphics class to, surprisingly, draw a line. Lines are drawn between two points, the starting circle and the destination circle (I used Point objects to set where the lines are drawn but there are a few overloads for DrawLine).
As you can see the map looks very messy with lines intersecting circles and other lines. I’m not too sure at the moment how I’m going to tidy it up. I’ll look into it more tonight and tomorrow and post my findings. The map at the moment isn’t displaying relationship strength or any other information I want it too. I’ll leave that until last, I’d rather have it display cleanly first.
There won’t be any programming done tomorrow (well, at least on this project) since I’ll be heading out for a change. If I’ve figured out how to implement a cleaner graph I will start work on that Saturday and hopefully muse about any problems I’m having and how they can be fixed while I’m away. 7/19/2006 Friends Drawn.
Here is tonight’s screen shot, as you can see the map is now drawing some of the other friends. This was pretty simple do with how I set up the draw text and circle code. The DrawFriends() method selects all friends that are parents in their relationships, or don’t have any relationships. Each person is then drawn on the map and after they drawn the code checks if they have any children and if they do the child friend is drawn, which then checks if that child has any friends, this is done using recursion and allows an infinite amount of relationships, in case you wanted to track a few hundred generations of family?
Another major development from last night’s screenshot is the circles and text looking 100% better. I was talking to a friend this morning and he gave me some tips on how to make it look better. By using the following two lines.
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
This applies Anti Aliasing to the drawn shapes and lines and the drawn text. Anti Aliasing makes the drawn text and circles look smoother by removing the ‘jaggies’ or sharp edges. How does it do it? Magic. Pure unadulterated magic. Wikipedia may be more correct than I am though, so if you want to know I’d suggest you go here.
I’d also like to retract something I said yesterday, you can make a rectangle with out using integers. RectangleF is the object you use for that. I should pressed the down key a few more times :)
So now that friends are being drawn on the map what next? I need to fix a small but annoying problem I’m having with the drawing of the control. If there are too many friends to display the map continues trying to draw them and giving the user the too popular message, over and over again. I’ve tried setting variables so it isn’t displayed any more and I’ve tried only displaying it once the map has finished drawing, but it’s coming up multiple times for reason. I’ve spent a disproportionate amount of time on a problem that should be simple. Once I’ve nailed that down I’ll start adding links between the circles, I think this part of the application will be the most troublesome. If I can get this part finished before I go away I’ll be very happy. 7/18/2006 Too Popular!
Linked above is the latest screenshot of my application, similar to yesterdays except the text positioning has been fixed up (though it’s still a little buggy) and there are multiple circles with my name in it, why? I’m really popular with my self as the message box says.
What the screenshot is really demonstrating is code to determine when the map can not draw any fit any more circles in it. Usually these would be friend circles but I’ve not got that far yet and just created an event to draw the owner circle multiple times. I didn’t get much besides this done today, I spent far too long doing my head in thinking about I can check if a circle is intersecting another circle. Which annoyed me because the answer was really simple; I’m not sure why I didn’t come up with it sooner.
The DrawEllipse() method can take a rectangle to draw the ellipse in. For me it’s a lot easier to work out if a square is over lapping another square, especially when the squares are in a rectangular container, so this is the solution I used. At the moment a circle is 20% of the original panel width, the space between circles is the circle width / 2. After each circle is drawn the coordinates for the next circle are updated, if the previous circle is at X, Y the next circle has to be at (X + circle size + ½ circle size), Y unless that X coordinate (plus a circle) is greater than the panel width. In that case the coordinates need to be X, (Y + circle size + ½ circle size). This fell into place when I realised circles could be represented by squares.
One thing I found a little annoying was that when creating a rectangle it couldn’t take float values for the size. So there is a bit of casting and rounding going on to get integers out of floats. So when I say ½ circle size I really mean Math.Round(circle size / 2, 0);.
Today was pretty successful, even though I didn’t accomplish what I set out to achieve (drawing friends on the map). I’ll attempt to get friends drawn on the map tomorrow if time is on my side. Speaking of time I’ll be taking some out Sunday and Monday, I’m having a mini holiday to the south west of Western Australia which will be extremely relaxing, so no blog entries on those days. :) 7/17/2006 Application Screenshot.
It’s all coming together; well at least the screen shot makes it appear that way. I didn’t get much time after work today to get much done. Though I did some design on paper to work out exactly what I needed to create and how that should be done. I’m still a little unclear on a few things, but I’ll get there in the end. One other part of the design of the control I did today was creating the formulae (formulas? www.dictionary.com says both are acceptable.) for ranking friends and events, they (especially the friends formula) could use some fine tuning, and who knows I might change it entirely before I actually implement it :)
The actual implementation of the friend map control is similar to the code I posted yesterday. Except here I have the panel’s paint method calling other methods to draw the individual parts. Drawing friends and links between people is going to be a fairly involved process and putting it all in the panel’s paint method would be messy to say the least.
Tomorrow I plan on cleaning up the code so the text in the initial circle is drawn in the middle and fixing a few other things (at the moment my name is hard coded, I’ll change that to dynamic tomorrow). Once I’m happy with that I’ll begin adding code for drawing the circles of other friends. I’m thinking of selecting all friends from the friends table that don’t have links, or are parents in their links and then one by one draw each friend on the map, and if they have links draw their links. I’m not quite sure how I’ll make the map look pretty with out having circles or links between friends over lapping each other and I’m sure I’ll run into quite a few issues I’m not yet aware about. So we’ll see where I’m at tomorrow. 7/16/2006 GDI+ Amateur
Linked above is a screenshot of what I accomplished last night, not overly productive, to be fair though it’s really my first time trying to draw something using System.Drawing class. The main reason I go little done was because I didn’t know what I was doing for the most part and why my picture wasn’t drawing. So after trying by my self to get the code working I turned to Google and apparently the mistakes I was making are really common for first timers.
I was trying to draw in a PictureBox by creating a graphics object from it, Graphics g = pboxImage.CreateGraphics();. While this allows the program to draw on the picture box when changes are made they aren’t saved because the changes are made above the PictureBox rather than actually on the PictureBox’s image. In my case I was trying to draw this way before the form loaded, and then when it was loaded it refreshed and my changes were lost.
This was all made clear to me after reading an excellent FAQ by Bob Powell at http://www.bobpowell.net/faqmain.htm the very first question deals with the issue I was having, if only I had searched earlier :). In the first question Bob discusses why the PictureBox isn’t a fit solution and goes on to suggest alternatives. I chose to store my graphic in a panel since I want a container for it. Another advantage over the PictureBox is that panels are scrollable by default, meaning I don’t have to do any extra work to make it scroll like I would with a PictureBox.
The code for the above application is very simple; I’ll paste the main part of it below.
private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, 0, 0, panel1.Width, panel1.Height);
Pen blackPen = new Pen(Color.Black); g.DrawEllipse(blackPen, 35, 5, 200, 200);
SolidBrush textBrush = new SolidBrush(Color.Black); g.DrawString("Neil Bamber", new Font("Verdana", 20), textBrush, 50, 85);
textBrush.Dispose(); blackPen.Dispose(); g.Dispose(); }
The panel1_Paint() method is called whenever the panel needs to be redrawn, so if a user minimises and maximises the application or moves a window over the application and then moves it away, the panel needs to be redrawn. This is why drawing on top of the picture box with a “stolen” graphics object does not work. The next line creates a Graphics object for us to use. The Graphics class contains all sorts of methods for drawing most things you can think of, In this example I’m drawing rectangles, circles and text (though drawing text isn’t new to my application, I’ve used the DrawString() function plenty of times in my owner drawn ListBoxes).
The FillRectangle() function fills the panel with a white rectangle that starts in the upper left corner, and is the height and width of the panel. The next line creates a Pen object for the DrawEllipse() method to use. The DrawEllipse() method draws a circle using the created Pen, at 35 pixels across from the left of the application and 5 pixels down from the top, with a width and height of 200. The next line creates a SolidBrush object for use in the DrawString() method. The difference between a SolidBrush and a Pen object is that Pens are used to draw lines and curves where as a SolidBrush is used to fill graphics such as the circle drawn by the Pen. The DrawString() method draws the text (in my case Neil Bamber, in the Verdana) font on the Panel. It doesn’t get much more Hello World than this :).
The next 3 lines dispose of the objects created during the method. It’s always proper practice to dispose of the objects you’ve created when you won’t need them anymore. Disposing of an object frees the resources it uses up so another object can use them. Freeing the resources used by objects that are no longer needed improves application performance because your application won’t be using as much memory. Of course the C# Garbage Collector will eventually free them, but managing your own memory where you can is better than not.
I think this post shows how little I know about GDI+ and how much work I’ll have to do get the control finished in time. Today I’ll be away from the computer although that may be a good thing because it will give me time to think about the best way to create the control, and the formula for ranking friends. 7/15/2006 Found.
Linked above is the promised screen shot of my search form in action. As you can see searching for my friend Arron (I don’t know why his parents spelled his name wrong either) returns his friend entry, a friend note, two events, and three event notes. I coded the rest of the functionality today, after last night’s blog post I thought I’d take a shower to wake me up so I could soldier on, but not after I just laid down for a minute. Oops I fell asleep; at least my dry jeans got an extra 8 hours of wear.
There are still a few niggling bugs with the search form though I wanted it finished a few days ago so they will remain unless I have time at the end of the competition to clean them up. I’m hoping to have a few days to add polish to my application, at the moment it’s a little rough in places, though I think that’s to be expected in all the competition applications given the timeframe and feature sets that are being delivered.
I’m going to take a bit of a break for the rest of today, read a little (Currently reading Musashi by Eiji Yoshikawa, it’s not a tech book so I’ve not added it to my reading list on the side) and play 360 a little, I’ve had a busy week. I’ll begin work on the much talked about FriendMap control tonight and post screenshots and thoughts of and on my progress tomorrow. 7/14/2006 Searching.
Above is a picture of the search form in action. At the moment the search only looks at friends and only at dates so it’s not too useful. I’ll write the rest of the form in what’s left of tonight and tomorrow morning; I just wanted to get an entry up while I’m still able to write coherently. Ignore the relevancy score it’s hard coded for the moment :)
Over the last few days I’ve been thinking about how to fetch the search data from the database, in the majority of searches I’ve written previously I knew what data the user wanted and consequently where in the database it was likely to be, or allowed them to select a field from the database they wanted to search and then enter their terms. Searching allows a user choose what they want to search, limit the results to a particular date range and (or) enter a string to limit the results further. This is a little different than writing select * from table where $fieldName like ‘%$search%’ like I’m used to.
So over the past few days I’ve been thinking about the best way to perform the search. Do I restrict the text box, as well as two DateTimePickers, to a certain field? This isn’t an optimum solution because a user may not be able to find what they want, how do I know if a user wants to search by First Known or Birthday. Do I write a multitude of queries to query all possible fields something could be in? That could work because it would return the appropriate results, but it would be time consuming (not to mention boring) to write and fairly inefficient. In the end I decided on writing three queries that limit results based on the birthday, first known, and event date fields and then further checking the results against the search criteria. I’ll explain further.
After a user clicks the search button, there are checks to see what they are searching for, in the screenshots case, friends. The application selects all records that match the date criteria for both birthday and first known. The results are put into a DataTable and then duplicates removed. The DataTable is then processed and any records that match the criteria are added to an ArrayList of Result objects. The Result ArrayList is then drawn in the ListBox and the user sees (hopefully) what they wanted to see.
I’ll post another screen shot of the search tomorrow showing different result types and hopefully different relevancy scores. I'll also go back through this entry and fix any mistakes I've made due to falling asleep :) 7/13/2006 Misc Part 2.Following up yesterdays post about a couple of problems I had with SQL Server 2005 and Visual C# 2005 Express Editions I thought today I’d make a post about a few features that I really like and what could be done to further improve them. Keep in mind what I suggest may already be there and I don’t know it, if that’s the case I’d appreciate people commenting on my ignorance. :)
One of the features of the C# language and Visual C# 2005 that is somewhat insignificant compared to other more grand features is regions. Regions allow you group sections of code together and then collapse them in Visual C# with a tag for the collapsed region. So for example in my application the manage events and manage friends form are some what large code wise. To make navigating through the code easier I’ve grouped the code into tab sections (like the forms) and collapsed parts that I’m not concerned with at the moment. For example,
#region Links Tab Code private bool LinkFieldCheck() { if (cmbLinkPerson.SelectedValue != null && cmbLinkRelationship.SelectedValue != null) return true; else return false; } #endregion
would be displayed as “Links Tab Code”. Obviously there is more code in the region in my application, but you get the idea. While using regions and moving code into them I thought of two changes that could be made in Visual C# to make them even more effective.
If you have a large file with many lines of code, that don’t have any particular order and you want to move the functions into appropriate regions you have to scroll up and down cutting and pasting code. Or if you have a few rather large regions open and you want to move between them, again, a lot of scrolling. One way to alleviate this would be to assign keyboard shorts to a region. It would allow people who are familiar with keyboard short cuts (as most developers are in their IDE of choice) to quickly move between regions that are thousands of lines apart.
Another region improvement could be the automatic grouping of code on a form. For example if I’ve created a form and want to clean it up a little bit and I have three or four different GroupBoxes, if I could press a button and have it group by those GroupBoxes that would be handy.
One other improvement I thought of while creating all the custom controls relates to the Solution Explorer window. In my project I’m starting to get a lot of forms and controls in the Window and I can’t imagine what it would be like for a large project. Having a filter or allowing a user to add folders to store things in would improve the readability of the Solution Explorer and allow people to find what they were looking for more quickly. These folders or groups could also be displayed in the tab strip drop down menu (on the right, left of the x button) that is just below the ToolBars in Visual C# 2005.
This ends my two part series on problems and features I like about the Express suite of products. Tomorrow I'll be getting back into real development and will hopefully have a working search form to show off. 7/12/2006 Misc.Unfortunately no major code additions today, the search form is still where it was yesterday, and with another event on the calendar for tomorrow night It’ll be Friday before I can work on it properly again. Over the next two days I’ll talk about a few topics regarding Visual C# 2005 Express Edition and SQL Server 2005 Express Edition from a usage point of view. Today I’ll mention problems I’ve come across recently and tomorrow I’ll move on to features that I really like and I think could be improved.
One issue I have with SQL Server 2005 was made apparent when I was changing the query that fills the friend list DataGridView on the main form. When I was first fleshing out the application I just put a query in that would display friends, their rating, and the last seen date. I didn’t limit the results to the most recent last seen date because I just wanted to get something running. I recently fixed this so it did in fact limit the results to the most recent, last seen date. Below is the query.
select people.person_id, people.name, people.rating, max(events.date) as date from events, owner_people, people, event_attendees where event_attendees.event_id = events.event_id and owner_people.person_id = event_attendees.person_id and owner_people.person_id = people.person_id and owner_people.owner_id = @mapOwnerID group by people.person_id, people.name, people.rating
At first though this didn’t work, when I ran the query I was getting the error that I couldn’t group by people.name (and therefore not select it) because it was a text, ntext, or image field. Not being able to group by a text field seemed pretty strange, but I figured I’d find a way around it and I did. I changed the people.name field type to varchar(max) since it wasn’t listed in the error list and sounded like it allowed the user to enter a lot of characters (I don’t really like limiting user input, some one may have a really long name :)). Once I did that it worked, but I was intrigued by just how big varchar(max) is. After googling I found that varchar(max) has the same 2gb limit as the text type, if it’s pretty much the same data type with the same size limitations and content, why can’t I group by text as well as varchar(max)? I might be missing something and if I am I’d love for some one to leave a comment informing me. :)
The second and final part of this post relates to Visual C# 2005 and is, unfortunately, a little vaguer than the first part. I’d guess that this is related to the copying and pasting of ToolStrip controls since that’s when it seems to happen. I’ve been rushing to get forms completed and a lot of the ToolStrips in my application are of the same format (either Save/New or Delete buttons) and I’ve taken to copying and pasting the controls into group boxes. The ToolStrips copy and paste fine, and work as they should, however at some point the Visible property gets to False for some reason. If I figure out the exact steps to duplicate the issue I’ll post them, but that’s the best I’ve got at the moment. It’s not too major, just a minor annoyance.
I’ll take a minor annoyance for a nearly fully featured IDE though. :)
|
|
|