Here I will post problems I and my colleagues met and solutions we found.

Wednesday, April 30, 2008

Using Control.Dock in WinForms does not work as it should.

Simple rule, if it's not Dock.Full, use panels as containers. Otherwise it's unpredictable when it works, and when not.

Sunday, April 27, 2008

How to browse for computer name

I never thought that a simple task of browsing for a computer name would be such a pain. Nevertheless it was.

What I need is to give user the dialog to choose computer from his local network.

First step:
WPF does not have FolderBrowser dialog. Well, we can use Windows.Forms for that. The have FolderBrowserDialog.

Step two:
In my dialog I wanted to start search from "Network". FolderBrowserDialog has RootFolder property for that. But enumeration does not support Network folder. I don't know why they removed it, because technically all they had to do is to add one enumeration value with proper value setting. So, that was the first obstacle.

Step three:
Doing some research I found class System.Windows.Forms.Design.FolderNameEditor from System.Design.dll. It's not perfect, but I could make it work easily and this one could start from folder Network. However, when I did that the return value was empty string.

Step four:
I started to research again. Now I found that Win32 method SHBrowseForFolder that is actually called behind the scene, returns computer name in very weird way. It retuns it not where directory path is usually returned, but in field name displayname. And that, for sure, was not handled properly in this System.Windows.Forms.Design.FolderNameEditor class.

Step five:
I researched some more and found a component ShellFolderBrowser at CodeProject. Now guess what? It didn't have RootFolder. So, I was where I started from.

Step six:
I decided that I researched enough. At this point it become faster for me to just write some code. Since there are plenty of classes that can support folder browsing in general, I decided not to write "universal" component or something like that. I just wrote simple method to choose computer name. It was based on ShellFolderBrowser I found at CodeProject (Author: Rama Krishna Vavilala) and some rip off from System.Windows.Forms.Design.FolderNameEditor extracted using Reflector.

It's draft, simple and not pretending to be component for general use. However, if you are interested, you can download the code from here ComputerBrowserZip. Again, you can learn more from looking at .NET code by Reflector or to ShellFolderBrowser.

Thursday, April 10, 2008

BindingComplete, Exception and DevExpress TextEdit

In our current application we are using CSLA and DevExpress.

While CSLA provides validation rules, they allow to continue data modification even when some property has incorrect value. What I wanted to achieve was little bit different. I wanted to not allow assign incorrect values. The logical approach for me was to throw exception in property setter. But then it took me sometime to figure out how to handle this exception.

DevExpress TextEdit just return "Invalid value" as ErrorText. The exception I raised was just lost. After researching he subject I finally understood how it works.

1. When data assigned to control, it calls OnValidating method.
2. The method puts data to the object through binding
3. Exception raised in property setter
4. This exception is caught by Binding object itself
5. If FormattingEnabled property of Binding object is set to true, then exception is not raised again. Instead, BindingComplete event is raised
6. Cancel is set to true and that value returned to OnValidating
7. Here is some specifics for TextEdit (or BaseEdit for that matters), it has InvalidValue event, but there is no information about exception available, it just puts "Invalid Value" to ErrorText.

So, final solution for me was
1. Since I use BindingSource object, I handle BindingSouce.BindingComplete event with this code


public virtual void bindingSource_BindingComplete(object sender, BindingCompleteEventArgs e)
{
if (e.BindingCompleteState == BindingCompleteState.Exception)
{
MessageBox.Show(MainForm.MainForm, e.ErrorText, Properties.Messages.labelError, MessageBoxButtons.OK, MessageBoxIcon.Error);
e.Binding.ReadValue();
}
}

Than for InvalidValue event I have


private void BaseEditInvalidValueHandler(object sender, DevExpress.XtraEditors.Controls.InvalidValueExceptionEventArgs e)
{
if ((e.Exception is WarningException) && (e.Exception.InnerException == null))
e.ExceptionMode = DevExpress.XtraEditors.Controls.ExceptionMode.NoAction;
else
e.ExceptionMode = DevExpress.XtraEditors.Controls.ExceptionMode.ThrowException;
}



And of cause, there is topic at MSDN for that, http://msdn2.microsoft.com/en-us/library/k26k86tb.aspx

Update:
BindingSourceRefresh component from CSLA handles refreshing in BindingComplete event

Tuesday, April 01, 2008

Aliases work in order clause in MS-SQL 2005

Not that I solved any problem but, today I accidentally found that aliases work in order clause if not used in functions. For example, this will work.

select c.Name, l.Value Lookup
from Customer c
left outer join LookupValue l on l.id = c.LookupId
order by Lookup

This didn't work in Oracle four years ago, where l.Value had to be used instead. And this is really nice.