DataGridColumn Click Event

Oct 6, 2008 at 2:19 PM
How do I handle a click event on a DataGridColumn (for example, when the user clicks on a DataGridHyperlinkColumn?).  I didn't see an event for this on the element.

Thanks.
-Larry
Coordinator
Oct 7, 2008 at 1:30 AM
DataGridColumn derives directly from DependencyObject so there is no Click event on a column.  There is a click event on a DataGridCell if you want to listen to that.  For a DataGridHyperlinkColumn scenario there are a couple of ways to handle this.  If you want to use a click event you can do something like the following:

<

 

dg:DataGridHyperlinkColumn Header="Homepage" CanUserSort="False" DataFieldBinding="{Binding Path=Homepage}">
    <dg:DataGridHyperlinkColumn.ElementStyle>
        <Style TargetType="TextBlock">
            <EventSetter Event="Hyperlink.Click" Handler="OnHyperlinkClick" />
        </Style>
    </dg:DataGridHyperlinkColumn.ElementStyle>
</dg:DataGridHyperlinkColumn>

private void OnHyperlinkClick(object sender, RoutedEventArgs e)
{
    Process.Start((e.Source as Hyperlink).NavigateUri.ToString());
}


Another way to handle it is to put the DataGrid in a NavigationWindow, then the hyperlink should work automatically.

Oct 7, 2008 at 6:16 PM
Thanks, this worked great!  But would you mind explaining what's going on under the covers?  I assume TextBlock is part of the DataGridHyperlinkColumn's visual tree, but I'm not understanding why the style has to target that.  Couldn't the style just target the Hyperlink and set its click event?

-Larry
Coordinator
Oct 7, 2008 at 8:03 PM
Each column has an ElementStyle and EditingElementStyle where you have access to set properties on the visual tree in both editing states.  The stock columns (text, checkbox, combobox, hyperlink) each have a hard coded visual element for each state.  For the hyperlink column the element in the non-editing state is a TextBlock (which wraps a hyperlink).  So the style that you set on the ElementStyle for a DataGridHyperlinkColumn has to be a TextBlock.  The fact that Hyperlink.Click is a routed event is very helpful in this situation.
Oct 7, 2008 at 8:15 PM
Makes sense.  Thanks for the explanation!
Nov 4, 2008 at 3:31 PM

I've inherited DataGrid and placed my xaml styles etc in a file which I access via a ResourceDictionary. If I add a style into that xaml file it says it can't find the handler "OnHyperlinkClick", which is correct because I don't have any code behind that class. So I created a xaml file for my inherited class which looks like this:-

<dg:DataGrid x:Class="SPF.Client.WPF.EnhancedDataGrid"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:dg="clr-namespace:SPF.Client.WPF.Controls;assembly=SPFClientWPFBase"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"
    xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
    xmlns:local="clr-namespace:SPF.Client.WPF"       
    >
    <dg:DataGrid.Resources>
            <Style x:Key="SPFDataGridHyperlinkStyle" TargetType="TextBlock">
                <EventSetter Event="Hyperlink.Click" Handler="OnHyperlinkClicked" />
            </Style>
    </dg:DataGrid.Resources>
   
</dg:DataGrid>

And was hoping the following line would work, I've done this by trapping OnAutoGeneratingColumn which creates the DataGridHyperLinkColumn

 

CType(lobjColumn, ListEditHyperlinkColumn).ElementStyle = CType(Me.FindResource("SPFDataGridHyperlinkStyle"), Style)

 

 

But me.Resources is empty and I can't work out where to add the xaml??

So I then tried to create the Style in code:-

                Dim lobjHyperLinkStyle As New Style(GetType(TextBlock))
                lobjHyperLinkStyle.Setters.Add(New EventSetter(TextBlock.MouseDownEvent, EnhancedGridHyperlinkClick))
                CType(lobjColumn, ListEditHyperlinkColumn).ElementStyle = lobjHyperLinkStyle

Which works until I get an exception in DataGridBoundColumn.ApplyStyle line 172 the exception is handlertype is not valid.

any tips most appreciated.

Coordinator
Nov 4, 2008 at 10:45 PM
Instead on "TextBlock.MouseDownEvent", have you tried "Hyperlink.Click"?
Nov 4, 2008 at 11:45 PM
Hi, I actually just got it working using the code below:-

                'Dim lobjSetter As New System.Windows.EventSetter
                'lobjSetter.Event = System.Windows.Documents.Hyperlink.ClickEvent
                'lobjSetter.Handler = New System.Windows.RoutedEventHandler(AddressOf Me.OnHyperlinkClicked)
                'Dim lobjHyperLinkStyle As New Style(GetType(TextBlock))
                'lobjHyperLinkStyle.Setters.Add(lobjSetter)
                'CType(lobjColumn, ListEditHyperlinkColumn).ElementStyle = lobjHyperLinkStyle

In my world I display another window and on clicking ok I then want to update the hyperlink text on the originally clicked cell, I couldn't work out how to do that. I managed to set the text on the textbox but not the hyperlink. Here is my event handler using the above code:-

        'Public Sub OnHyperLinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        '    Dim lobjTextBlock As TextBlock = TryCast(sender, TextBlock)
        '                    'Dim lobjLink As System.Windows.Documents.Hyperlink = DirectCast(e.OriginalSource, System.Windows.Documents.Hyperlink)
        '                    'lobjLink.TargetName = lobjCellWrapper.ToString
        '                    'lobjLink.Background = New SolidColorBrush(Colors.Yellow)

Any ideas?
Coordinator
Nov 5, 2008 at 12:47 PM

In your OnHyperLinkClicked method, try something like this instead:

ContentPresenter
cp = Helper.GetVisualChild<ContentPresenter>(sender as Visual);
cp.Content = "<url string>"
;

Where GetVisualChild looks like this:

public static T GetVisualChild<T>(Visual parent) where T : Visual
{
    T child =
default(T);
    int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < numVisuals; i++)
    {
        Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
        child = v
as T;
        if (child == null)
        {
            child = GetVisualChild<T>(v);
        }
        if (child != null)
        {
            break;
        }
    }
    return child;
}

 

 

Nov 5, 2008 at 10:10 PM
Now I've upgraded to V1 of the datagrid the code above which added the handler for the hyperlink click event is now giving an error whilst building the grid.

'Hyperlink' TargetType does not match type of element 'TextBlock'. in DataGridBoundColumn line 165.

This was working yesterday on the CTP version - any ideas?

All I've done is inherit from DataGridHyperLinkColumn and set the style in code using:-

                Dim lobjSetter As New System.Windows.EventSetter
                lobjSetter.Event = System.Windows.Documents.Hyperlink.ClickEvent
                lobjSetter.Handler = New System.Windows.RoutedEventHandler(AddressOf Me.OnHyperlinkClicked)
                Dim lobjHyperLinkStyle As New Style(GetType(System.Windows.Documents.Hyperlink))
                lobjHyperLinkStyle.Setters.Add(lobjSetter)
                CType(lobjColumn, ListEditHyperlinkColumn).EditingElementStyle = lobjHyperLinkStyle


 
Oct 8, 2009 at 3:49 AM

"Process.Start((e.Source as Hyperlink).NavigateUri.ToString());"

 

I have tried this and NavigateURI is returning a null value. The datagrid hyperlink column is displaying integers.

So what now??