Как показать всплывающую подсказку только при отсутствии активности? - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть сетка данных с всплывающей подсказкой, чтобы показать некоторую информацию. Отображается через 3 секунды.

Проблема в том, что если я прокручиваю сетку данных колесиком мыши, чтобы найти строку, отображается всплывающая подсказка, и она продолжает отображаться, хотя я прокручиваю, поэтому многие строки скрыты всплывающей подсказкой.

Можно ли настроить всплывающую подсказку, которая будет отображаться только в случае отсутствия активности, но начать отсчитывать секунды, если я использую клавиши или колесо мыши для искать строку?

Спасибо.

1 Ответ

0 голосов
/ 16 апреля 2020

Да, это вообще возможно. Самый простой способ - изменить размещение всплывающей подсказки или настроить задержку показа.

Вы можете управлять поведением всплывающей подсказки, используя ToolTipService, который предоставляет набор прикрепленных свойств:

<Ellipse Height="25" Width="50" 
      Fill="Gray" 
      HorizontalAlignment="Left"
      ToolTipService.InitialShowDelay="1000"
      ToolTipService.ShowDuration="7000"
      ToolTipService.BetweenShowDelay="2000"
      ToolTipService.Placement="Right" 
      ToolTipService.PlacementRectangle="50,0,0,0"
      ToolTipService.HorizontalOffset="10" 
      ToolTipService.VerticalOffset="20"
      ToolTipService.HasDropShadow="false"
      ToolTipService.ShowOnDisabled="true" 
      ToolTipService.IsEnabled="true"
      ToolTipOpening="whenToolTipOpens"
      ToolTipClosing="whenToolTipCloses"
      >
  <Ellipse.ToolTip>
    <BulletDecorator>
      <BulletDecorator.Bullet>
        <Ellipse Height="10" Width="20" Fill="Blue"/>
      </BulletDecorator.Bullet>
      <TextBlock>Uses the ToolTipService class</TextBlock>
    </BulletDecorator>
  </Ellipse.ToolTip>
</Ellipse>

Если это не удовлетворяет вашим требованиям, вы можете вызвать всплывающую подсказку напрямую, установив ToolTiupService.IsEnabled присоединенное свойство. Это требует обновления фокуса, потому что после того, как подсказка отключена и исчезла, пользователь должен снова вызвать подсказку. По этой причине я бы предпочел вместо этого переключать TooTip.Opacity.

Другая проблема состоит в том, что фактический столбец не является частью визуального дерева сетки данных.
Чтобы справиться с этим несколько проблематичным c обстоятельством, я ввел свойство stati c для привязки шаблона к нему. Поскольку это свойство stati c и нам нужно уведомление PropertyChanged (DependencyProperty не будет работать, поскольку оно связано с экземпляром), я также реализовал версию stati c INotifyPropertyChanged.

Решение основано на прикрепленном поведении, которое прослушивает перенаправленное событие ScrollViewer.ScrollChanged для переключения ToolTip.Opacity через привязку данных:

DataGrid.cs

class DataGrid : DependencyObject, INotifyPropertyChanged
{
  #region IsDisableToolTipOnScrollEnabled attached property

  public static readonly DependencyProperty IsDisableToolTipOnScrollEnabledProperty = DependencyProperty.RegisterAttached(
    "IsDisableToolTipOnScrollEnabled", 
    typeof(bool), 
    typeof(DataGrid), 
    new PropertyMetadata(default(bool), OnIsDisableToolTipOnScrollEnabledChanged));

  public static void SetIsDisableToolTipOnScrollEnabled(DependencyObject attachingElement, bool value) 
    => attachingElement.SetValue(DataGrid.IsDisableToolTipOnScrollEnabledProperty, value);

  public static bool GetIsDisableToolTipOnScrollEnabled(DependencyObject attachingElement)
    => (bool) attachingElement.GetValue(DataGrid.IsDisableToolTipOnScrollEnabledProperty);

  #endregion IsDisableToolTipOnScrollEnabled attached property

  private static double opacityValue;   
  public static double OpacityValue
  {
    get => opacityValue;
    set 
    {
      opacityValue = value; 
      OnStaticPropertyChanged();
    }
  }

  private static DispatcherTimer Timer { get; set; }

  static DataGrid()
  {
    DataGrid.Timer = new DispatcherTimer();

    // Set reset tooltip reappearance to 3 seconds 
    DataGrid.Timer.Interval = TimeSpan.FromSeconds(3);

    DataGrid.Timer.Tick += OnTimerElapsed;
    DataGrid.OpacityValue = 1.0;
  }

  private static void OnIsDisableToolTipOnScrollEnabledChanged(DependencyObject attachingElement, DependencyPropertyChangedEventArgs e)
  {
    if (!(attachingElement is System.Windows.Controls.DataGrid dataGrid))
    {
      throw new ArgumentException("Attaching element must be of type DataGrid");
    }

    var behaviorIsEnabled = (bool) e.NewValue;
    if (behaviorIsEnabled)
    {
      EnableScrollHandling(dataGrid);
    }
    else
    {
      DisableScrollHandling(dataGrid);
    }
  }

  private static void EnableScrollHandling(System.Windows.Controls.DataGrid dataGrid)
  {
    if (dataGrid.IsLoaded)
    {
      dataGrid.AddHandler(ScrollViewer.ScrollChangedEvent, new RoutedEventHandler(OnScrollChanged));
    }
    else
    {
      dataGrid.Loaded += (sender, args) =>
        dataGrid.AddHandler(ScrollViewer.ScrollChangedEvent, new RoutedEventHandler(OnScrollChanged));
    }
  }

  private static void DisableScrollHandling(System.Windows.Controls.DataGrid dataGrid)
  {
    dataGrid.RemoveHandler(ScrollViewer.ScrollChangedEvent, new RoutedEventHandler(OnScrollChanged));
  }

  private static void OnScrollChanged(object sender, RoutedEventArgs e)
  {
    DataGrid.OpacityValue = 1.0;

    // Start or reset the timer on scroll
    DataGrid.Timer.Start();
  }

  private static void OnTimerElapsed(object sender, EventArgs e)
  {
    var timer = sender as DispatcherTimer;
    timer.Stop();
    DataGrid.IsToolTipVisible = true;
    DataGrid.OpacityValue = 1.0;
  }

  public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
  private static void OnStaticPropertyChanged([CallerMemberName] string propertyName = null)
  {
    DataGrid.StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
  }
}

Использование

<!-- Enable the behavior by setting IsDisableToolTipOnScrollEnabled to true -->
<DataGrid x:Name="DataGrid" 
          DataGrid.IsDisableToolTipOnScrollEnabled="True">
  <DataGrid.Resources>

    <!-- Bind the ToolTip.Opacity to the static property of the attached behavior -->
    <Style TargetType="ToolTip">
      <Setter Property="Opacity" Value="{Binding Path=(viewModels:DataGrid.OpacityValue)}" />
    </Style>
  </DataGrid.Resources>

  <!-- Setup the cell tooltips -->
  <DataGrid.CellStyle>
    <Style TargetType="DataGridCell">
      <Setter Property="ToolTip" Value="{Binding Value}" />
    </Style>
  </DataGrid.CellStyle>
</DataGrid>  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...