4
votes

I am quite new to WPF, there is so much to learn and I think I'm getting there, slowly. I have a DataGrid which is used for display and user input, it's quite a tricky Grid as it is the main focus of the entire application. I have some columns that are read-only and I have used a CellStyle Setter to set KeyboardNavigation.IsTabStop to False to keep user input focused on the important columns and that works fine. I would like a couple of the read-only columns to be hyperlinks that show a tooltip and do not receive the focus, however I am struggling to write the XAML that will achieve all three requirements at the same time.

One of the columns is to indicate if the item on the row has any Notes. I have used the following XAML to display a HasNotes property in the cell in a DataGridTemplateColumn and on the Tooltip show the actual notes, in the Notes property:

            <DataGridTemplateColumn x:Name="NotesColumn" Header="Notes">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding HasNotes, Mode=OneWay}">
                            <TextBlock.ToolTip>
                                <TextBlock Text="{Binding Notes}" MaxWidth="300" TextWrapping="Wrap" />
                            </TextBlock.ToolTip>
                        </TextBlock>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellStyle>
                    <Style>
                        <Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
                    </Style>
                </DataGridTemplateColumn.CellStyle>
            </DataGridTemplateColumn>

That works fine but I would like to make it a Hyperlink instead so the user can do something with the Notes when they click on the cell contents.

I have another column which is a DataGridHyperlinkColumn used to display a Unit of Measurement on a hyperlink and when clicked the user can change the unit. (The reason I have done it like this, rather than a ComboBox for example, is because as much as I want the user to be able to change the unit I want to make the interface such that it is a very deliberate act to change the unit, not something that can be done accidentally). The following XAML puts the Hyperlink column on for Unit

            <DataGridHyperlinkColumn x:Name="ResultUnitLink" Binding="{Binding Path=Unit.Code}" Header="Unit" Width="Auto" IsReadOnly="True">
                <DataGridHyperlinkColumn.CellStyle>
                    <Style>
                        <Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
                    </Style>
                </DataGridHyperlinkColumn.CellStyle>
                <DataGridHyperlinkColumn.ElementStyle>
                    <Style>
                        <EventSetter Event="Hyperlink.Click" Handler="ChangeUnit" />
                    </Style>
                </DataGridHyperlinkColumn.ElementStyle>
            </DataGridHyperlinkColumn>

One problem with the XAML for the Hyperlink column is that the IsTabStop = False doesn't appear to work, when tabbing through the Grid my hyperlink column still receives the focus, unlike the other columns where I've used a setter to change IsTabStop. If push comes to shove I could live with that but I'd rather not.

What I actually want from both those columns is an amalgamation of the two appearances/behaviours i.e. Columns where the data is displayed on a hyperlink, where TabStop = False and which display a tooltip of a different property when hovered over.

Can anyone help advise me how to get a column that achieves the following:

  1. Hyperlink displaying one property
  2. Tooltip displaying a different property
  3. IsTabStop = False that actually works when used with a hyperlink

Thanks in advance to anyone who can help.

1

1 Answers

4
votes

I've had issues with the Hyperlink in the past, so have this Style which I use for Labels or Buttons to make them look like Hyperlinks. Try making your column Template into a Button or a Label and applying this style.

<Style x:Key="ButtonAsLinkStyle" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                    <ContentPresenter ContentStringFormat="{TemplateBinding ContentStringFormat}" />
                </TextBlock>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Foreground" Value="Blue" />
    <Setter Property="Cursor" Value="Hand" />
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Foreground" Value="Red" />
        </Trigger>
    </Style.Triggers>
</Style>