Posted by: Xiaonan Ji | December 2, 2009

Escaping curly brackets

In string format, put two curly brackets together to escape it. For example, string.format(“{{{0}}}”, 34) outputs {34}.

Posted by: Xiaonan Ji | November 30, 2009

Work More Effectively As A Developer

From Peopleware:

There are several ways to make project or task (time) estimation. The estimation can be made by managers, developers themselves, managers + developers or system analysts. If estimation is made by managers, developers work in lowest efficiency. Managers + developers make things better. Amazingly, if estimation is made by developers themselves, they tend to work better. Note that Baidu (the biggest search engine company in China) uses this way to estimate project schedules. But this is not the best way. Developers work even better when estimation is made by system analysts. The book says that because system analysts are the best people that can make best estimation and developers work better under better estimation. I just partly understand this.

But wait a second, what if no schedule is to be made? Developers work best if no schedule is made or need! Just wake me up when you done. Why? I guess, it is a matter of human pride. Let me summarize this up. If you are told be a manager to finish something in 2 days, and you think the manager doesn’t know better than you about the work, you wouldn’t work very hard to meet her schedule. If you and the manager agree that the work should be done in 2 days, you are involved and it is now part of your responsibility to meet the schedule. But the manager still interferes.  Now the manager asks you and you tell her that you will finish it in 2 days. What now? You need to work very hard to meet your own schedule. Otherwise, everyone else will think you are not very capable of doing your work and you lose credibility. When the system analyst says that you can finish the work in 2 days, she probably knows it well and you feel happy to meet her correct schedule. In above situations, you always have a schedule to meet. You don’t have to finish the work in 1 day if the schedule says you can/should finish it in 2 days. What if there is no schedule at all? The earlier you can finish the work, the better you impress everyone else and the better you feel in the company, and the greater the achievement is, and the harder you will work.

Developers are simply persons working with computers and programs everyday. The only thing they want best is the achievement, the agreement from everyone else about his ability. They will fight very hard to gain the honor. All they want is: to prove they can work quickly; to prove their code works beautifully; to see their code is used by others; to know everyone knows the above truth. If you can let them get all these, they will work harder than you can image.

Posted by: Xiaonan Ji | November 11, 2009

Enum Type in C#

Enum items by default start from 0. So if you have an enum WeekDays { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}; Then by default, Monday has a value of 0 and Tuesday has a value of 1 and so on. An enum variable has a default value of (WeekDays)0 (not null as objects).

You can explicitly change the numeric value of enum items. If you set a number to an enum item, the following items’ numeric values are increased by 1 sequentially. Make sure you set the numeric values in a valid way. For example, if you set enum WeekDays { Monday = 1, Tuesday = 0, Wednesday, Thursday, Friday, Saturday, Sunday}; Then WeekDays.Monday will be conflicted to WeekDays.Wednesday and you will have trouble separating the two conflicted values.

Until next time, happy coding.

Posted by: Xiaonan Ji | November 10, 2009

Pay attention when changing menu options

Many Windows applications use menus to organize the actions or options provided by the software. In some cases, the menu items will be changed. For example, according to a license, some options are disabled and invisible to users. Hiding menu items is a simple task in .NET but you must pay special attention when toolstrip separators are also used to group options in menus.

When a drop down menu list contains menu items and separators, and all menu items in a group are hidden because of certain reason, you will see two separators next to each other vertically in the menu drop down list, with nothing in between them. This is a UI defect that is easy to be overlooked.

A solution is to provide a function for removing menu items, for example, the following function.

   1:  private static void RemoveMenuItem_(ToolStripMenuItem item, ToolStripMenuItem parent)
   2:  {
   3:      int indexOfRemoving = parent.DropDownItems.IndexOf(item);
   4:  
   5:      if(indexOfRemoving + 1 < parent.DropDownItems.Count) {
   6:          var separatorBelow = parent.DropDownItems[indexOfRemoving + 1] as ToolStripSeparator;
   7:  
   8:          if (separatorBelow != null)
   9:          {
  10:              int indexOfAboveRemoving = indexOfRemoving - 1;
  11:              if (indexOfAboveRemoving < 0 || parent.DropDownItems[indexOfAboveRemoving] is ToolStripSeparator)
  12:              {
  13:                  separatorBelow.Visible = false;
  14:                  parent.DropDownItems.Remove(separatorBelow);
  15:              }
  16:          }
  17:      }
  18:  
  19:      item.Enabled = false;
  20:      item.Visible = false;
  21:  
  22:      parent.DropDownItems.Remove(item);
  23:  }

The above code takes care of hiding and removing menu items and separators if necessary.

Until next time, happy coding.

Posted by: Xiaonan Ji | September 30, 2009

Use “as” as a type casting method with care

In C#, we can use the keyword “as” to cast an object from one type to another. Its purpose is similar as direct casting. Consider the following code:

1. Object o = new Car();
2. Car car = o as Car;
3. Car anotherCar = (Car)o;

Line 2 and 3 have similar purpose. Line 2 uses the keyword “as” to cast o to type Car and line 3 uses direct cast. The difference is, if o cannot be casted to Car, line 2 will fail silently and object car will be assigned to null while line 3 will throw an exception explicitly.

If the logic implies that o should always be a type of Car otherwise it indicates a programming bug, then line 3 is preferred than line 2 because we don’t want to hide any programming bugs from being discovered as early as possible. But if o is not necessarily a type of Car and it is according to logic behind the code, then line 2 is obviously the choice. Consider the code below:

1. Object o = new Sedan();
2. …
3. Sedan s = o as Sedan;
4. Wagon w = o as Wagon;
5. Hatch h = o as Hatch;
6. if(s != null) { //handle sedan. }
7. else if(w != null) { //handle wagon. }
8. else if(h != null) { //handle hatch. }

In this code, we try to test the type of object o and do accordingly. We are not sure which type o is so we perform a test casting. Obviously we don’t want exception to be thrown from each test casting. So using the keyword “as” is the choice over direct casting.

By the way, I do not mean the above code is well designed because it tries to cast a generic type to descendent types and this normally breaks the rules of object oriented design. But this example clearly gives difference of using “as” to cast and using direct casting.

Until next time, happy coding.

Posted by: Xiaonan Ji | September 25, 2009

Be cautious when using ToolStrip and Data Binding

If you use ToolStrip on a form that has data binding usage, you need to be careful. Clicking any item on a ToolStrip control doesn’t remove your cursor from any control on the form. For example, you edit a textbox on the form and directly click save item on ToolStrip, you will find that your cursor stays in the textbox the whole way. Now the problem is, since the cursor is never moved out of the textbox, the textbox “thought” that it itself is in edit and the data binding underlying will not be triggered. If the underlying data binding is not triggered, you may not be able to save the latest change if you purely rely on data binding to update underlying business object or whatever.

When I came across this problem, I just happen to have a button always sitting on my form. Whenever I click something on the ToolStrip control, I manually set the button to get the focus. In that way, whatever controls that holding data that need to be updated will be updated via data binding mechanism. This is just a quick & easy solution but it works. Whatever method suits you, you need to be careful that ToolStrip control operation doesn’t crab the focus from the main form and thus data binding may not work (in the right timing) for you!

Until next time, happy coding!

Posted by: Xiaonan Ji | September 24, 2009

Make StatusStrip Item Right Aligned

Two strips are frequently used in WinForm in .net. One is ToolStrip and the other is StatusStrip. Usually we want to put some items on these strips and make them align to right. In ToolStrip, it is fairly easy. Set the item’s Align property to right does the work. In StatusStrip, it is not so obvious how to because there is no such Align property. A workaround way is to create a text item on the StatusStrip, set its text to empty and set its Sprint property to true and place the item in between your left aligned and right aligned item(s).

Until next time, happy coding!

Posted by: Xiaonan Ji | September 21, 2009

Data binding with nullable types in C#

Binding a nullable type to a control in C# doesn’t seem to be as simple as binding a normal primary type. Firstly, if you want to bind a nullable type to a textbox, remember to set FormattingEnable property of the Binding to be true. Otherwise, you will find that every time you try to type in some value in the textbox and step away from it, it clears the value. Secondly, you will find that leaving the textbox empty doesn’t tell the nullable type to set itself to null. To achieve that affect, you need to take care of the Binding instance’s Parse event. Suppose you try to bind a nullable<double> to a textbox, remember to hook the following event to the Parse event of the Binding instance:

void Text_Parse(object sender, ConvertEventArgs e){if(e.Value == null || e.value.ToString().Length == 0) e.Value = null;}

After hooking this event to the Binding instance, clear the textbox content will set the underlying nullable<double> to null.

Until next time, happy coding.

Posted by: Xiaonan Ji | August 19, 2009

One-way and Two-way DataBindings

In .Net, there are two types of data bindings, one is called one-way data binding and the other is called two-way data binding. One-way data binding means that after you bind a data source to a control, any change made on the control will be reflected to the underlying data source. But if you change the underlying data source (via other means than through the control), the control will not capture the change and reflect it in UI. Two-way data binding complements this limit. In a two-way binding, any change on the control is automatically reflected on the underlying data source and any change on the underlying data source is automatically reflected on the control.

To impliment a one-way binding is very easy:

List<DemoClass> instances_ = new List<DemoClass>();
BindingSource bs_ = new BindingSource();
bs_.DataSource = instances_;
dgv.DataSource = bs_;

Above four lines create a one-way data binding. dgv is the DataGridView. Here we rely on its own mechanism to populate columns and fill the grid with the underly data source instances_.

The problem is, when you try to add a new instance of DemoClass to instances_, the change is not reflected on the grid. If you change a property value of an existing instance, the change is not reflected on the grid as well. Two works need to be done for these.

Firstly, DemoClass has to impliment INotifyPropertyChanged interface. Implimenting this interface will add a public delegate to the DemoClass. Don’t worry about the delegate, data binding ensures the delegate will be assigned by other classes necessary. The key is to call this delegate on every setter method of every published property:

public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(string propertyName){
if(PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

Here, I create a private method calling the delegate so we save some redundant code. What I now need to do is to ensure every setting calls the private method, passing the property’s name to it:

private string property_;

public string Property{
set{
property_ = value;
NotifyPropertyChanged(“Property”);
}
}

OK. Now, if we programatically change the Property value of an instance in instances_ list, the change will be immediately reflected to the grid.

How about adding and removing items from instances_? Unfortunately, we cannot let our List<DemoClass> to impliment INotifyPropertyChanged interface. A good news is, there is another class for this purpos, that is, BindingList<T>. BindingList<T> can be used exactly the same as List<T>. The difference is that BindingList<T> supports two-way binding. If we simply change the type of instances_ from List<DemoClass> to BindingList<DemoClass>, the adding and removing DemoClass changes will immediately reflect to the UI. And until now, we implement a two-way binding.

Until next time, happy coding!

Posted by: Xiaonan Ji | August 18, 2009

How to avoid multiple clicks on a DataGridViewComboBoxCell?

If you have used DataGridViewComboBoxColumn on a DataGridView, you must have the experience of clicking a DataGridViewComboBoxCell multiple times before the dropdown list shows itself. This can be annoying. One quick fix is to set the EditStyle of the DataGridView to EditOnEnter. This has a small bug which only happens when the row selection mode is allowed. Be specific, when you set the EditStyle to EditOnEnter and you select a whole row by selecting the row header, the row is selected and one cell will be in edit mode, which is not the desired behavior. There is a workaround: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98504.

Until next time, happen coding!

Older Posts »

Categories