Tag Archives: Windows Forms

Presenting FilterList

Earlier today i decided to add ‘Filtering’ to my SortableBindingList. This resulted in writing a FilterList class. This class can be easily used as following:

void textBoxFilter_KeyUp(object sender, KeyEventArgs e)
{
 var filterChars = this.textBoxFilter.Text.ToLower();
 this.Filter(filterChars);
}

void Filter(string filterChars)
{
 var persons = (FilterList<person>)this.dataGridView1.DataSource;
 persons.Filter(p => p.Firstname.ToLower().Contains(filterChars));
}

I even created a screencast to demonstrate it:

[mediaplayer src='http://www.timvw.be/screencasts/filterlist.wmv' width=512 height=344]

Presenting ControlStateMachine

Here is a situation we are all familiar with: A form that only displays a certain set of controls depending on the mode or state of the application. Let me start with an example: At design time there are three buttons

screenshot of flowlayoutpanel with three buttons: edit, save and cancel.

The user can look at the data and decide to edit it:

screenshot of flowlayoutpanel with only one visible button: edit.

Or the user is editing the data and can decide to commit or discard her changes:

screenshot of flowlayoutpanel with two visible buttons: save and cancel.

A couple of years i ago i used to spread such display logic all over my code and it was hard to figure out which control was visible at a given point. Later on i refactored that code and encapsulated it in functions like: MakeControlsForDisplayVisible and MakeControlsForEditVisible which felt like a huge improvement. These days i have the feeling that a very simple state machine can improve the readability even better.

Ok, so how simple is simple? Currently the requirements list is pretty limited:

screenshot of unittests for controlstatemachine

Anyway, here is how i would write the code today (Yeah, for a stupid example this looks like overkill):

private void InitializeButtonLayoutPanelMachine()
{
 controlStateMachine = new ControlStateMachine<displayAndEditStates>(buttonLayoutPanel);

 controlStateMachine.WhenStateChangesTo(DisplayAndEditStates.Display)
  .TheOnlyVisibleControlsAre(buttonEdit);

 controlStateMachine.WhenStateChangesTo(DisplayAndEditStates.Edit)
  .TheOnlyVisibleControlsAre(buttonSave, buttonCancel);
}

As always, here is the source: ControlStateMachine and WhenChangingState.

Presenting ControlChanges

Because i noticed that i kept writing the same operations on control over and over again i decided to capture them in a couple of functions. I presume most of you have done this already. Here is the list of operations:

screenshot of a class diagram with the following operations: MakeVisible, MakeInvisible and TheOnlyVisibleControlsAre.

In case it is not clear what these methods should do i have defined the following specifications for them:

screenshot of requirements list for controlchanges.

Get the code here: ControlChanges and WhenExecutingControlChanges. Stay tuned for more!

Experimenting with ControlStateMachine and Fluent interfaces

A long time ago i read Build your own CAB series and recently i noticed that there is a wiki: Presentation Patterns Wiki! and it inspired me to experiment with state machines. Here are a couple of examples:

controlStateMachine = new ControlStateMachine<states>(this);

controlStateMachine.AfterEachStateChange()
 .Do(MakeRelevantButtonsVisible);

controlStateMachine.WhenStateChangesTo(States.RetrievingSubscriptionPeriod)
 .TheOnlyVisibleControlsAre(flowLayoutPanel1, datePicker1);

controlStateMachine.WhenStateChangesTo(States.RetrievingCustomerInformation)
 .MakeVisible(customerInput1)
 .Do(() => customerInput1.Dock = DockStyle.Fill);

controlStateMachine.WhenStateChangesTo(States.Ready)
 .MakeInvisible(customerInput1);

And here is another example:

wizardStateMachine = new WizardStateMachine<states>(controlStateMachine);

wizardStateMachine.InState(States.RetrievingSubscriptionPeriod)
 .OnCommand(WizardCommands.Next)
  .TransitionTo(States.RetrievingCustomerInformation);

wizardStateMachine.InState(States.RetrievingCustomerInformation)
 .OnCommand(WizardCommands.Back)
  .TransitionTo(States.RetrievingSubscriptionPeriod)
 .OnCommand(WizardCommands.Finish)
  .TransitionTo(States.Ready);

wizardStateMachine.InState(States.Ready)
 .OnCommand(WizardCommands.New)
  .Do(() => MessageBox.Show("Currently not supported"));

Stay tuned for future posts where i describe the problem space that have lead to this API.

Presenting AssemblyTypePicker

I really like the way the Object Browser makes the types in an assembly visible. Because i have a couple of programs that require a given type as input, i have decided to add a TypeTree control to BeTimvwFramework that mimicks the Object Browser. Here are a couple of screenshots of the control in a demo application that allows the user to generate interfaces and wrapper classes based on a selected type:

screenshot of assemblytypepicker with no values


screenshot of dialog that requests the user to pick an assembly file


screenshot of dialog that requests the user to pick a type in the previously selected assembly

Feel free to download CodeGenerator.zip.

Display WorkItems in a WinForms application

Using the Microsoft.TeamFoundation.WorkItemTracking.Controls assembly it is possibe to display WorkItems. Here is a little demo application that will display all the WorkItems that have been changed by one of the given users in the given range:

screenshot of workitemtracker application

Feel free to download the source: WorkItemTracker.zip

Edit (05/03/2008):

Refactored the code a little and added some features like sortable columns, loading default tfsserver and users from App.Config, …

How the name of an embedded resource is generated in a C# project

A while ago i was wondering how the name of an embedded resource is generated in a C# project. Earlier today i was looking in Microsoft.CSharp.targets and found the answer:

The CreateManifestResourceNames target create the manifest resource names from the .RESX files.

[IN]
@(ResxWithNoCulture) - The names the non-culture .RESX files.
@(ResxWithCulture) - The names the culture .RESX files.
@(NonResxWithNoCulture) - The names of the non-culture non-RESX files (like bitmaps, etc).
@(NonResxWithCulture) - The names of the culture non-RESX files (like bitmaps, etc).

[OUT]
@(ManifestResourceWithNoCultureName) - The corresponding manifest resource name (.RESOURCE)
@(ManifestResourceWithCultureName) - The corresponding manifest resource name (.RESOURCE)
@(ManifestNonResxWithNoCulture) - The corresponding manifest resource name.
@(ManifestNonResxWithCulture) - The corresponding manifest resource name.

For C# applications the transformation is like:

Resources1.resx => RootNamespace.Resources1 => Build into main assembly
SubFolder\Resources1.resx => RootNamespace.SubFolder.Resources1 => Build into main assembly
Resources1.fr.resx => RootNamespace.Resources1.fr => Build into satellite assembly
Resources1.notaculture.resx => RootNamespace.Resources1.notaculture => Build into main assembly

For other project systems, this transformation may be different.

With Attrice Corporation Microsoft Build Sidekick v2 you can easily visualize the flow throughout the targets via Tools -> View Targets Diagram.

Using DateTimePicker and Custom Format

Today we ran into a nasty problem with DateTimePickerFormat.Custom. We allow the user to input a month/date with a DateTimePicker as following (nothing fancy):

private void Form1_Load(object sender, EventArgs e)
{
 this.dateTimePicker1.Value = new DateTime(2007, 8, 31);
 this.dateTimePicker1.Format = DateTimePickerFormat.Custom;
 this.dateTimePicker1.CustomFormat = "MM/yyyy";
}

Now, change to 09/2007 and notice that you get an Exception, because the control tries to create an unrepresentable new DateTime(2007, 8+1, 31). Thus, if you’re going to use the DateTimePicker for MM/yyyy input make sure to set it’s value to a DateTimeTime with a day component that exists for all months/years (thus a value between 1 and 28).

Addendum: As usual, super moderator and MVP Hans Passant provided a nice workaround for the problem:)

public class MonthPicker : DateTimePicker {
  public MonthPicker() {
    this.Format = DateTimePickerFormat.Custom;
    this.CustomFormat = "MM/yyyy";
    DateTime now = DateTime.Now;
    this.Value = new DateTime(now.Year, now.Month, 1);
  }
  protected override void WndProc(ref Message m) {
    if (m.Msg == 0x204e) {
      NMHDR hdr = (NMHDR)m.GetLParam(typeof(NMHDR));
      if (hdr.code == -759) {
        NMDATETIMECHANGE dt = (NMDATETIMECHANGE)m.GetLParam(typeof(NMDATETIMECHANGE));
        this.Value = new DateTime(dt.st.wYear, dt.st.wMonth, 1);
        return;
      }
    }
    base.WndProc(ref m);
  }
  // P/Invoke declarations
  [StructLayout(LayoutKind.Sequential)]
  private struct NMHDR {
    public IntPtr hWnd;
    public IntPtr id;
    public int code;
  }
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  private class NMDATETIMECHANGE {
    public NMHDR nmhdr;
    public int dwFlags;
    public SYSTEMTIME st;
  }
  [StructLayout(LayoutKind.Sequential)]
  private class SYSTEMTIME {
    public short wYear;
    public short wMonth;
    public short wDayOfWeek;
    public short wDay;
    public short wHour;
    public short wMinute;
    public short wSecond;
    public short wMilliseconds;
  }
}

Bending the code generation of IExtenderProvider to your will

In Exploring CodeDomSerializer i already explained how we can modify the code that the Visual Studio designer generates for us. With a typical IExtenderProvider the designer generates an initializer, SetXXX methods and a variable declaration, which looks like:

this.constantsExtenderProvider1 = new WindowsApplication1.ConstantsExtenderProvider();

this.constantsExtenderProvider1.SetConstants(this.button1, new string[] {
 "Operation1",
 "Operation5"});

this.constantsExtenderProvider1.SetConstants(this, null);

private ConstantsExtenderProvider constantsExtenderProvider1;

Now, what if we’re not happy with those generated SetXXX methods on each Component? The problem is that this code is not generated by the serializer for the ConstantsExtenderProvider but by the serializers for the Components. An easy workaround for this problem is to set the DesignerSerializationVisibilityAttribute on the GetXXX method in our IExtenderProvider to Hidden.

With those ugly SetXXX methods out of the way it’s up to us to do it better. We do this by implementing a custom serializer for our ConstantsExtenderProvider:

class ConstantsSerializer<t> : CodeDomSerializer
{
 public override object Serialize(IDesignerSerializationManager manager, object value)
 {
  ConstantsExtenderProvider provider = value as ConstantsExtenderProvider;

  CodeDomSerializer baseClassSerializer = manager.GetSerializer(typeof(ConstantsExtenderProvider).BaseType, typeof(CodeDomSerializer)) as CodeDomSerializer;
  CodeStatementCollection statements = baseClassSerializer.Serialize(manager, value) as CodeStatementCollection;

  IDesignerHost host = (IDesignerHost)manager.GetService(typeof(IDesignerHost));
  ComponentCollection components = host.Container.Components;
  this.SerializeExtender(manager, provider, components, statements);

  return statements;
 }

 private void SerializeExtender(IDesignerSerializationManager manager, ConstantsExtenderProvider provider, ComponentCollection components, CodeStatementCollection statements)
 {
  foreach (IComponent component in components)
  {
   Control control = component as Control;
   if (control != null && (control as Form == null))
   {
    CodeMethodInvokeExpression methodcall = new CodeMethodInvokeExpression(base.SerializeToExpression(manager, provider), "SetConstants");
    methodcall.Parameters.Add(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), control.Name));

    string[] constants = provider.GetConstants(control);
    if (constants != null)
    {
     StringBuilder sb = new StringBuilder();
     sb.Append("new string[] { ");

     foreach (string constant in constants)
     {
      sb.Append(typeof(T).FullName);
      sb.Append(".");
      sb.Append(constant);
      sb.Append(", ");
     }

     sb.Remove(sb.Length - 2, 2);
     sb.Append(" }");

     methodcall.Parameters.Add(new CodeSnippetExpression(sb.ToString()));
    }
    else
    {
     methodcall.Parameters.Add(new CodePrimitiveExpression(null));
    }

    statements.Add(methodcall);
   }
  }
 }
}

And now the generated code looks like:

this.constantsExtenderProvider1.SetConstants(this.button1, new string[] { WindowsApplication1.Constants.Operation1, WindowsApplication1.Constants.Operation5 });

As always, feel free to download the ConstantsExtenderProvider source.

Debugging custom UITypeEditors

If you read this you’re probably gonna think: What a moron! Anyway, i’m sharing this in the hope that i’ll be the last to undergo the following. In order to test my custom UITypeEditor i did the following:

  1. Create a UserControl
  2. Add a property to the control
  3. Add an Editor attribute to the property
  4. Build
  5. Drag a UserControl on the designer form
  6. Test via Visual Studio’s Property Window if the UITypeEditor works as expected
  7. Everytime i changed some code: Restart Visual Studio, load the project and repeat 6.

A tedious task to say the least. Yesterday i figured out that i could drag a PropertyGrid on the designer form, and set it’s SelectedObject property to a class with a property that uses the custom UITypeEditor; Instead of having to reload visual studio i can simply start a debug session, and click on the property in the PropertyGrid. Now it’s a breeze to develop custom UITypeEditors :)

private void Form1_Load(object sender, EventArgs e)
{
 // display an instance of PersonEntry,
 // a class with a property that should use the custom UITypeEditor i want to test
 this.propertyGrid1.SelectedObject = new PersonEntry(new Person("Tim", "Van Wassenhove"));
}

public class PersonEntry
{
 ...

 // instruct the PropertyGrid to use my custom PersonUITypeEditor
 [Editor(typeof(PersonUITypeEditor), typeof(UITypeEditor))]
 public Person Person
 {
  get { return this.person; }
  set { this.person = value; }
 }
}

public class PersonUITypeEditor : UITypeEditor
{
 public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
 {
  return UITypeEditorEditStyle.Modal;
 }

 public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
 {
  Person person = value as Person;

  IWindowsFormsEditorService svc = context.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
  if (svc != null)
  {
   using (PersonEditorForm personEditorForm = new PersonEditorForm(person))
   {
    if (svc.ShowDialog(personEditorForm) == DialogResult.OK)
    {
     return personEditorForm.Person;
    }
   }
  }

  return value;
 }
}