Monday, April 26, 2010

Auto Complete Box Control in WPF

If you have work in silverlight 3.0 then you have see the auto complete box control is there to help the user to search from the possible list of value when user type in text box. When I have used that control I though of similar control in the WPF , I have search on net by using Google and found some simple auto complete text box control on net.But I have decided to create one for myself and then share it with people on my blog. So here is my first ever control which I want to share it with you. Below are the two image of the control. In the first image you can see simple text box control and a button control but in the second image you see the drop down with possible list of matched values.




Let us start with properties of the control , Below are the list of properties which are offered by the control. I have given some description for each of the property. First I have listed the dataSource property which is used to set the data source for the control. Then is the displayColumn Name which is used to display value of the column when you click on the dropDown list. DataSource and DisplayColumnName Properties are primary properties which user has to set otherwise control will not work.
Property
Description
DataSourceData source to display dropdown list.
DisplayColumnNameName of the column which is used to display in the text box when user select from the dropdown list.
DropdownHeightUsed to set the height of the Dropdown list
ReturnValueReturn value is a DataRow, whole row of the dataSource table.
MinimumSearchLengthMinimum search length is used to search in the list, e.g if set to 2 then search is perform and dropdown list will be open when the text box contain atleast 2 characters.

Then is the DropDownHeight which is used to set the height of the dropDownList. The ReturnValue is the dataRow , when user select from the dropDownlist then it will return whole row of the DataSource , so if you can get the whole selected record and you can get whatever you want from that row, mean primary key, display Column name etc.
The interesting part of the control is when you use the BindingColumn class to pass the parameter to the bindingColumn function of the autoCompleteBox class. The Class consist of four properties HeaderText, BindingColumnName, FilterOption and IsSearchable. HeaderText is used to display Text as header in grid and BindingColumnName is used to bind the column from the dataSource to the grid to display the value. The filder option Consist of 3 option StartWith, Contains and EndWith option, what ever you pass that column is search accordingly in the list and the IsSearable is used to sepecify whether the current column is search-able or not.
Hope you will like that control. if you have any suggestion then please share it with me, I have included the autoCompleteBox dll in that project. You can use it and if you need source code I will share it with you. You can download the source code from here
All and any comments / bugs / suggestions are welcomed!

Saturday, April 10, 2010

RowDetailTemplate of DataGrid control

When I started my learning of silver light 3.0, and see the control offered by the tool, one of the controls which I like most in every programming language is the data grid control. The feature offered by the new data grid control are very good especially the RowDetail. Which is the best feature from my point of view as you can show additional detail of the record in the Row Detail, it is mostly used when you have situation where you need to show parent and child records. When I used data grid control in silver light application the question in my mind was how to display data grid in the RowDetail, and I have search on it on Google but didn’t find good solution at that time. But now once again I have tried again and now this time I have find the solution of displaying data grid in the RowDetail. Below is the main data grid when user didn't click on any of the row.
And here is the row detail of the grid when user click on any of the data grid row, to see the more detail about the record.

Let us start with our example code I have one data grid control and in that data grid control I have placed another data grid control which is placed in the RowDetail template. I have two classes one for with the name of Persons and second one with the name of PersonDetail. In the Person class I have following properties user id, first name, last name, email address and the contact number. In PersonDetail class I have Parent ID, Programming language and the skills level properties. I have just used the programming languages such as WPF, WCF , silver light, php , asp.net etc. for just display purpose and each record in the Persons class has two child records so that when user click on any of the row , it shows its relevant record, I have also displayed the Parent ID in the child table so that you can see the relation ship id as well. Below is my xaml code, here you can see that I have placed grid control in the RowDetailTemplate of the main data grid, and I have also set the columns properties such as header , binding etc of the child data grid control.
<data:DataGrid Margin="5,5,5,0" x:Name="dgrdDataGrid" GridLinesVisibility="Horizontal" AutoGenerateColumns="False" VerticalAlignment="Top" RowDetailsVisibilityChanged="dgrdDataGrid_RowDetailsVisibilityChanged" IsReadOnly="True">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="User ID" Width="80" Binding="{Binding UserID}" CanUserReorder="False"/>
<data:DataGridTextColumn Header="First Name" Width="150" Binding="{Binding FirstName}" CanUserReorder="False" />
<data:DataGridTextColumn Header="Last Name" Width="150" Binding="{Binding LastName}" CanUserReorder="False"/>
<data:DataGridTextColumn Header="Email Address" Width="150" Binding="{Binding EmailID}" CanUserReorder="False"/>
<data:DataGridTextColumn Header="Contact" Width="100" Binding="{Binding ContactNumber}" CanUserReorder="False"/>
</data:DataGrid.Columns>
<data:DataGrid.RowDetailsTemplate>
<DataTemplate>
<data:DataGrid x:Name="dgrdRowDetail" Width="400" AutoGenerateColumns="False" HorizontalAlignment="Center" IsReadOnly="True">
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Parent ID" Binding="{Binding ParentID}"/>
<data:DataGridTextColumn Header="Programming Language" Binding="{Binding ProgrammingLanguages}"/>
<data:DataGridTextColumn Header="Skill Level" Binding="{Binding SkillLevel}"/>
</data:DataGrid.Columns>
</data:DataGrid>
</DataTemplate>
</data:DataGrid.RowDetailsTemplate>
</data:DataGrid>
Next the important thing is I have registered the RowDetailsVisibilityChanged event of the main data grid control , which is fired when RowDetailVisibilityMode property value changes, when user click on any of the row then it will fires , and in this event I will filter the records depending on the Persons ID and then assign it to the RowDetail data grid control.
Here is the complete code of the RowDetailVisibilityChanged event handler, here you can see that I have place if condition to check the dataContext of the row for null and then use form filter of the data to get only record which are matched with the current user id.

try
{
if (e.Row.DataContext != null)
{
var objCurrentRecordDetail = from tblPersonDetail in objPersonDetail
where tblPersonDetail.ParentID == ((Persons)e.Row.DataContext).UserID
select tblPersonDetail;

((DataGrid)e.DetailsElement).ItemsSource = objCurrentRecordDetail;
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message, "Error", MessageBoxButton.OK);
}
Next is the statement which is used to assigned the item source of the data grid which is placed in the RowDetail. Here I have used the EventArgs parameter of the RowDetailVisibilityChanged event handler and use the property DetailElement, as I have only one control in the RowDetail , so here I can find the main data grid control in the DetailElement property. Suppose if you have Grid layout in the RowDetail and you have your own display of the RowDetail then you can use e.DetailsElement.FindName("dgrdRowDetail") to find the data grid in my case and any of the control which you want to search in the grid control. In this case e.DetailElement Property will return you the grid control. Then you have to search for your control in that grid layout.You can download the source code from here
All and any comments / bugs / suggestions are welcomed!