Category Archives: GUI programming

Forcing binding update in TextBox

A typical usage of TextBox control in Silverlight is to bind it to a property and set the bind as two way. When the property changes, the TextBox is updated with the change and if the user changes the text in the TextBox, it is saved back to the property. Something like this:


<TextBox Text="{Binding Path=State, Mode=TwoWay}" />

A common problem developers face is when you have a TextBox control and a Submit button, which is enabled only when the data in TextBox is modified. The Submit button is not enabled until the LostFocus event of text box is fired. And LostFocus won’t be fired unless you click on something else. In this case, we can force the text to be updated. Register for TextChanged event and in this event handler, get the binding object and force an update.

 


<TextBox Text="{Binding Path=State, Mode=TwoWay}" TextChanged="textBox_TextChanged"/>

void textBox_TextChanged(object sender, TextChangedEventArgs e)
{

if(sender is TextBox)
{
TextBox tb = sender as TextBox;
BindingExpression binding = tb.GetBindingExpression(TextBox.TextProperty);
if (binding != null)
{
binding.UpdateSource();
}
}

}

Ta-da!

SelectionChangedEvent in RadGridView

If you have used RadGridView with a GridViewComboBoxColumn, you know it does not support SelectionChangedEvent directly. There are many scenarios where you want to handle some validation or perform some action when the user selects an item in a combo box but the absense of SelectionChangedEvent for GridViewComboBoxColumn makes this really hard. Good news is, there is a solution. Here it is, see if it helps.

Let’s say you have a RadGridView defined like this:


<telerik:RadGridView x:Name="myGridView">
 <telerik:RadGridView.Columns>
 <telerik:GridViewComboBoxColumn Header="Page" UniqueName="column1"  />
 </telerik:RadGridView.Columns>
</telerik:RadGridView>

 
In your code behind, preferably in the Loaded event, add this code:


this.AddHandler(RadComboBox.SelectionChangedEvent,
new Telerik.Windows.Controls.SelectionChangedEventHandler(ComboBox_SelectionChanged));

Add an event for Selection changed event. The name of your method and the event above should match.


 void ComboBox_SelectionChanged(object sender, RadRoutedEventArgs args)
 {
RadComboBox comboBox = (RadComboBox)args.OriginalSource;

if (comboBox.SelectedValue == null)
return;

// Get the current cell
GridViewCell cell = myGridView.CurrentCell;

// Handle the situation where a cell is null. It can be when you are adding a new row
if (cell == null)
{
return;
}

GridViewRowItem row = cell.ParentRow;
GridViewColumn col = cell.Column;

// This if block here is to handle only the combo box column desired. You can
// have multiple combobox columns and this event will be triggered for all of them.
// Handle what is required and ignore the rest
if (col.UniqueName != "column1") // Unique name that you specified in the XAML
{
return;
}

// YourDataObject is whatever data object you are using
YourDataObject item = comboBox.DataContext as YourDataObject;

//SelectedItem returns object. Convert it to whatever your binding object type is
object selectedItem = comboBox.SelectedItem;

// Now that you have your selected item, you can do whatever you want.
// In case you want to disable other cells on this row, just use row.Cells property.
}

That’s it. You are all set now.

Some points to note:
1. SelectionChanged event will be triggered for all combo box columns and combo boxes you have. You need to find out if the deisred combo box column is changed.
2. This event is triggered not only after the selection is changed, but also when the user just clicks on the combo box. There is a solution to handle this, but that’s another story altogether.
3. This was tried with VS 2010 and Silverlight 4.

Review: Introduction to Silverlight 3 by Laurence Moroney

The book intends to give an overview of the features in Silverlight 3. It starts with very basic things like creating a Hello world project in Silverlight 3, the different elements in SL3 project and hand coding all those elements outside the Visual Studio environment. Later on, the book dives into advanced-beginner topics like writing XAML code, using Expression Blend etc.

The book touches on different topics at a superficial level and doesn’t give deep insight into any of the topics. This is what is expected from an ‘Introduction’ book, so the purpose is served. There is a detailed section (couple of chapters) on UI controls available in SL3. It introduces basic controls like Button, Text Block, Label and moves on to slightly advanced controls like DataGrid, ScrollViewer etc. The author explains designing UI using XAML. This is a must for anyone who don’t have Blend. Learning XAML is the biggest challenge in XAML, in my opinion.

There is a small section on MVVM where the author discusses two-way data binding. I was hoping this section would be a bit deeper, but I guess that was not in the scope of this book.

The intention of the book is not to showcase the differences in SL3 and the previous versions of Silverlight. It isolates SL3 and focuses only on this version. For someone who is starting to learn Silvelright and chooses SL3 as the version, then this book is ideal to start with. The reader need not worry about the compatibility issues with older versions unnecessarily.

If you are looking for a quick familiarity to Silverlight 3, then this is the book for you.

Tagged , , ,

Hyperlink or Linklabel in Silverlight

Silverlight 3 does not have a control similar to link label. This post tells you how you can add a hyperlink or linklabel in Silverlight 3.

Expression Blend:

1. Create a Silverlight project.

2. Add a Text Block object. Change the text to suit your requirement, let’s say My Website.

3. Under Properties->Brush tab, change the color to R=0, G=0, B=204.

4. Under Properties->Text tab, click on the Underline button. This will add underline to the text.

5. Under Properties->Common Properties, change the Cursor to Hand. (Choose from the drop down list)

6. Under Events tab, double click on MouseLeftButtonUp to add a event handler. In the code-behind, you can open the desired website.

Modifying XAML:

1. Create a Silverlight project

2. In MainPage.xaml, add the following lines

<TextBlock Text="My Website" TextWrapping="Wrap" TextDecorations="Underline" Foreground="#FF0000CC" Cursor="Hand" MouseLeftButtonUp="TextBlock_MouseLeftButtonUp"/>

In the event handler, add the code to open your website.

Tagged , , , , , ,

Datagridview: Get SelectedIndex of DataGridViewComboBoxColumn

This seems to be a straight forward thing, but Microsoft only knows why this simple feature is not supported in DataGridView.

If you have a ComboBoxColumn in your DataGridView and you want to know what is the selected index of the combo box, then you need to do this:

1. Handle the EditingControlShowing event of DataGridView. In this event handler, check if the current column is of our interest. Then we create a temporary ComboBox object and get the selected index:


private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
if (dataGridView1.CurrentCell.ColumnIndex == 0)
{
// Check box column
ComboBox comboBox = e.Control as ComboBox;
comboBox.SelectedIndexChanged += new EventHandler(comboBox_SelectedIndexChanged);
}
}

void comboBox_SelectedIndexChanged(object sender, EventArgs e)
{
int selectedIndex = ((ComboBox)sender).SelectedIndex;
MessageBox.Show("Selected Index = " + selectedIndex);
}

A rather round-about solution where a simple one would have sufficed.

Right click on TreeView: Get the node clicked at

Problem:

There is a TreeView control with n number of nodes. When the user right clicks on the TreeView control, get the node on which the right click was performed.

Background:

In TreeView control, SelectedNode property is set whenever left click occurs. This is not true for right clicks. So, we need to have some workaround for this.

Solution 1:

The most popular solution is to handle the MouseDown event. Check if the click was a right click and then use the TreeView control’s GetNodeAt API to get the node which was clicked at.

private void treeView1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
TreeNode selectedNode = treeView1.GetNodeAt(e.X, e.Y);
MessageBox.Show("You clicked on node: " + selectedNode.Text);
}
}


Solution 2:

Handle the NodeMouseClick event. The TreeNodeMouseClickEventArgs has the node which was clicked at.

private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
MessageBox.Show("You clicked on node: " + e.Node.Text, "Solution 2");
}
}

SelectedNode property of a treeview is set whenever a left click occurs. Why can’t the same be applied for right click? Right click on a treeview is such a common UI event, that users will benefit from it.

Disable Close button in Windows form

To disable that little close button in your Windows form, either you can set the ControlBox field in Properties window to False or or add this two line in the contructor:

this.ControlBox = false;

Same goes for Maximize and Minimize boxes. Set it using Properties window or add these lines:


this.MaximizeBox = false;
this.MinimizeBox = false;

Simple, huh?

Main Form loses focus

Apologies if this post comes across as naive. I recently put my foot into the Windows Forms world and I have been learning new things. This might be a problem which all GUI programmers have encountered on day one and also know the solution to it. This post is to those souls like me who make a late entry into this magical world and seem to get lost, err… lose focus.

Problem:

We have a main form called MainForm. Whenever the user clicks a button on this MainForm, a method Copy in a class HelperClass is called. This method Copy uses the kernel call FileSystem.CopyFile to carry out the copying. One reason to use the kernel call is you need not re-write the progress bar and cancel features, just reuse the features provided by the kernel call. This will display the standard Windows file copying dialog with a cancel button.

The problem is, whenever you click Cancel on the file copying dialog, the MainForm loses focus.

Solution:

Since we are using the file copying dialog provided by the kernel, we have no access to the dialog directly. Hence, we cannot set the MainForm as the owner of the file copying dialog.

The solution to this problem is, in MainForm, right after we make a call to Copy method, set the focus back to MainForm.

    Copy(source, destination);
this.Focus();

Problem solved.