Kryptos-FR / markdig.wpf

A WPF library for xoofx/markdig https://github.com/xoofx/markdig
MIT License
162 stars 52 forks source link

Focus issues #37

Open alexrp opened 4 years ago

alexrp commented 4 years ago

Hello,

I'm using a MarkdownViewer in a WPF app I'm working on. I've run into some issues with focus:

  1. MarkdownViewer.Focusable is enabled by default which is probably going to be surprising to most users since it's a read-only control (I just disabled it myself).
  2. If NewsViewer.Markdown is empty, tabbing in the app still ends up giving focus to some hidden element within the viewer (not sure which).
  3. If NewsViewer.Markdown contains a hyperlink, tabbing will eventually give focus to that hyperlink, in addition to the previous point.

What I'd like to achieve is not allowing focus on any element within the MarkdownViewer. Is this possible?

Kryptos-FR commented 4 years ago

Same as in #38, you can override some of the styles of the default theme. Note that if you do bind the Commands.Hyperlink or the Commands.Image those clickable links are by definition focusable (so that the click can work), so you can't have both the are non-focusable and have the links working (as far as I understand WPF).

Note that to completely disable the focus, the FlowDocumentScrollViewer of the default theme ControlTemplate also need Focusable="False". That is not ideal, so I will think of a way to improve that.

In the meantime, overriding some styles from the generic theme will do the trick:

<Window x:Class="Markdig.Wpf.SampleApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:markdig="clr-namespace:Markdig.Wpf;assembly=Markdig.Wpf">
  <FrameworkElement.CommandBindings>
    <!--<CommandBinding Command="{x:Static markdig:Commands.Hyperlink}" Executed="OpenHyperlink" />-->
    <!--<CommandBinding Command="{x:Static markdig:Commands.Image}" Executed="ClickOnImage" />-->
  </FrameworkElement.CommandBindings>
  <FrameworkElement.Resources>
    <Style TargetType="markdig:MarkdownViewer">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="markdig:MarkdownViewer">
            <FlowDocumentScrollViewer Document="{TemplateBinding Document}" Focusable="False"
                                      ScrollViewer.HorizontalScrollBarVisibility="Visible"
                                      ScrollViewer.VerticalScrollBarVisibility="Visible" />
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
    <Style TargetType="{x:Type FlowDocument}" x:Key="{x:Static markdig:Styles.DocumentStyleKey}">
      <Setter Property="FontFamily" Value="Calibri" />
      <Setter Property="TextAlignment" Value="Left" />
      <Setter Property="Focusable" Value="False" />
    </Style>
    <Style TargetType="{x:Type Hyperlink}" x:Key="{x:Static markdig:Styles.HyperlinkStyleKey}">
      <Setter Property="Focusable" Value="False" />
    </Style>
    <Style TargetType="{x:Type Image}" x:Key="{x:Static markdig:Styles.ImageStyleKey}">
      <Setter Property="MaxHeight" Value="{Binding RelativeSource={RelativeSource Self}, Path=Source.(BitmapSource.PixelHeight)}" />
      <Setter Property="MaxWidth" Value="{Binding RelativeSource={RelativeSource Self}, Path=Source.(BitmapSource.PixelWidth)}" />
      <Setter Property="Focusable" Value="False" />
    </Style>
  </FrameworkElement.Resources>
  <DockPanel>
    <Button x:Name="ToggleExtensionsButton" DockPanel.Dock="Top" HorizontalAlignment="Center"
            Content="Toggle supported extensions" Click="ToggleExtensionsButton_OnClick" />
    <markdig:MarkdownViewer x:Name="Viewer" Focusable="False" />
  </DockPanel>
</Window>
alexrp commented 4 years ago

I'm not super familiar with WPF myself, so I could well be wrong, but I don't think a control has to be focusable to be clickable. I have some buttons in this project that I've set Focusable=false on but they're still clickable and still function when I press enter (and IsDefault=true). I don't know if the same applies to hyperlinks though.