2010-01-12 5 views

ответ

8

Прежде всего ... кредит на этот ответ отправляется Eric Burke. Он answered этот самый вопрос отправлен в группу WPF Disciples. Я подумал, что было бы полезно поставить этот ответ на StackOverflow тоже.

В принципе, вам необходимо анимировать свойство IsOpen всплывающего окна с помощью DiscreteBooleanKeyFrame.

Проверьте следующую XAML (который может быть легко вставлен в Kaxaml или другую свободную утилиту редактирования XAML):

<Page 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
> 
    <ContentPresenter> 
     <ContentPresenter.ContentTemplate> 
      <DataTemplate> 
       <Grid> 
        <CheckBox 
         x:Name="cb" 
         Width="100" 
         Height="40" 
         Content="Hover Over Me" 
        /> 
        <Popup 
         x:Name="popup" 
         Placement="Bottom" 
         PlacementTarget="{Binding ElementName=cb}" 
        > 
         <Border Width="400" Height="400" Background="Red"/> 
        </Popup> 
       </Grid> 
       <DataTemplate.Triggers> 
        <Trigger SourceName="cb" Property="IsMouseOver" Value="True"> 
         <Trigger.EnterActions> 
          <BeginStoryboard x:Name="bsb"> 
           <Storyboard> 
            <BooleanAnimationUsingKeyFrames 
             Storyboard.TargetName="popup" 
             Storyboard.TargetProperty="IsOpen" 
             FillBehavior="HoldEnd" 
            > 
             <DiscreteBooleanKeyFrame KeyTime="0:0:0.5" Value="True"/> 
            </BooleanAnimationUsingKeyFrames> 
           </Storyboard> 
          </BeginStoryboard> 
         </Trigger.EnterActions> 
         <Trigger.ExitActions> 
          <StopStoryboard BeginStoryboardName="bsb"/> 
         </Trigger.ExitActions> 
        </Trigger> 
       </DataTemplate.Triggers> 
      </DataTemplate> 
     </ContentPresenter.ContentTemplate> 
    </ContentPresenter> 
</Page> 

Пожалуйста, обратите внимание, что я немного ... изменил его оригинальное решение, чтобы вызвать IsOpen по сравнению с проверкой CheckBox, как и у него. Все в попытке заставить Popup вести себя немного как ToolTip.

10

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

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

_popupTimer = new DispatcherTimer(DispatcherPriority.Normal); 
_popupTimer.Interval = TimeSpan.FromMilliseconds(100); 
_popupTimer.Tick += (obj, e) => 
{ 
    _popup.IsOpen = true; 
}; 
_popupTimer.Start(); 

Для всплывающей подсказки типа поведения это может быть сделано на MouseEnter , Если вы хотите, чтобы закрыть всплывающее отверстие для какой-либо причине (например, если мышь покидает элемент управления до появления всплывающего окна), просто:

_popupTimer.Stop(); 

Update

Как cplotts obseved в комментарии, вы также захочет установить _popup.IsOpen = false в некоторых ситуациях в событии MouseLeave, в зависимости от вашей логики для обработки событий ввода/вывода мыши между вашим элементом управления и всплывающим окном. Имейте в виду, что вы обычно не хотите слепо устанавливать IsOpen=false на каждое событие MouseLeave, потому что он может это сделать, когда всплывающее окно появляется над ним. В некоторых ситуациях это приведет к появлению мерцающего всплывающего окна. Поэтому вам понадобится какая-то логика.

+0

Хороший вопрос ... и хорошая идея. Возможно, вы захотите также очистить значение IsOpen в MouseLeave в приведенном выше решении. – cplotts

+0

Да, вы, вероятно, захотите это сделать, но внимательно. Я уточню свой ответ, чтобы объяснить, что я имею в виду. –

+0

Рэй, огромное спасибо! Это была именно та функциональность, в которой я нуждался. – Stewbob

0
System.Windows.Controls.ToolTip tp = new System.Windows.Controls.ToolTip(); 

System.Windows.Threading.DispatcherTimer tooltipTimer = 
    new System.Windows.Threading.DispatcherTimer 
    (
     System.Windows.Threading.DispatcherPriority.Normal 
    ); 

private void TooltipInvalidCharacter() 
{ 
    tp.Content = 
     "A flie name cannot contain any of the following character :" + 
     "\n" + "\t" + "\\/: * ? \" < > |"; 

    tooltipTimer.Interval = TimeSpan.FromSeconds(5); 
    tooltipTimer.Tick += new EventHandler(tooltipTimer_Tick); 
    tp.IsOpen = true; 
    tooltipTimer.Start();  
} 

void tooltipTimer_Tick(object sender, EventArgs e) 
{ 
    tp.IsOpen = false; 
    tooltipTimer.Stop(); 
} 
+1

Хотя ваш ответ вообще не отвечает на вопрос, он вызывает тот факт, что вы часто хотите скрыть подсказку инструмента через некоторое время. Что-то иметь в виду. – cplotts

0

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

я изменил образец следующим образом:

  1. Создать анимацию «ClosePopop», который устанавливает IsOpen Ложь через 0,5 секунды. Я сделал это ресурсом, потому что он используется дважды.
  2. Для триггера IsMouseOver элемента управления добавьте ExitAction, который запустит анимацию ClosePopup. Это дает пользователю возможность переместить указатель мыши над всплывающим окном, прежде чем он закроется. Я назвал эту анимацию «bxb»
  3. Добавить триггер в свойство всплывающего окна IsMouseOver. На mouseover остановите (но не удаляйте) оригинальную анимацию Closexopup «bxb». Это оставляет всплывающее окно видимым; удаление анимации здесь сделает всплывающее окно закрытым.
  4. В выпадающем меню всплывающего окна запустите новую анимацию ClosePopup и удалите анимацию «bxb». Последний шаг критический, потому что в противном случае первая, остановленная анимация «bxb» сохранит всплывающее окно.

Эта версия превращает синюю попку, когда мышь над ней, чтобы вы могли видеть последовательность событий с помощью Kaxaml.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
<DataTemplate x:Key="TooltipPopup"> 
    <Grid> 
    <CheckBox 
     x:Name="cb" 
     Width="100" 
     Height="40" 
     Content="Hover Over Me"/> 
    <Popup 
     x:Name="popup" 
     Placement="Bottom" 
     PlacementTarget="{Binding ElementName=cb}"> 
     <Border x:Name="border" Width="400" Height="400" Background="Red"/> 
    </Popup> 
    </Grid> 
    <DataTemplate.Resources> 
    <Storyboard x:Key="ClosePopup"> 
     <BooleanAnimationUsingKeyFrames 
         Storyboard.TargetName="popup" 
         Storyboard.TargetProperty="IsOpen" 
         FillBehavior="Stop"> 
      <DiscreteBooleanKeyFrame KeyTime="0:0:0.5" Value="False"/> 
     </BooleanAnimationUsingKeyFrames> 
    </Storyboard> 
    </DataTemplate.Resources> 
    <DataTemplate.Triggers> 
    <Trigger SourceName="cb" Property="IsMouseOver" Value="True"> 
     <Trigger.EnterActions> 
      <BeginStoryboard x:Name="bsb" > 
       <Storyboard> 
        <BooleanAnimationUsingKeyFrames 
         Storyboard.TargetName="popup" 
         Storyboard.TargetProperty="IsOpen" 
         FillBehavior="HoldEnd"> 
         <DiscreteBooleanKeyFrame KeyTime="0:0:0.5" Value="True"/> 
        </BooleanAnimationUsingKeyFrames> 
       </Storyboard> 
      </BeginStoryboard> 
     </Trigger.EnterActions> 
     <Trigger.ExitActions> 
      <StopStoryboard BeginStoryboardName="bsb"/> 
      <BeginStoryboard x:Name="bxb" Storyboard="{StaticResource ClosePopup}"/> 
     </Trigger.ExitActions> 
    </Trigger> 
    <Trigger SourceName="popup" Property="IsMouseOver" Value="True"> 
     <Setter TargetName="border" Property="Background" Value="Blue"/> 
     <Trigger.EnterActions> 
      <StopStoryboard BeginStoryboardName="bxb"/> 
     </Trigger.EnterActions> 
     <Trigger.ExitActions> 
      <BeginStoryboard Storyboard="{StaticResource ClosePopup}"/> 
      <RemoveStoryboard BeginStoryboardName="bxb"/> 
     </Trigger.ExitActions> 
    </Trigger> 
    </DataTemplate.Triggers> 
</DataTemplate> 
</Page> 
12

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

<Style x:Key="TooltipPopupStyle" TargetType="Popup"> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding PlacementTarget.IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True"> 
      <DataTrigger.EnterActions> 
       <BeginStoryboard x:Name="OpenPopupStoryBoard" > 
        <Storyboard> 
         <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" FillBehavior="HoldEnd"> 
          <DiscreteBooleanKeyFrame KeyTime="0:0:0.25" Value="True"/> 
         </BooleanAnimationUsingKeyFrames> 
        </Storyboard> 
       </BeginStoryboard> 
      </DataTrigger.EnterActions> 
      <DataTrigger.ExitActions> 
       <PauseStoryboard BeginStoryboardName="OpenPopupStoryBoard"/> 
       <BeginStoryboard x:Name="ClosePopupStoryBoard"> 
        <Storyboard> 
         <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" FillBehavior="HoldEnd"> 
          <DiscreteBooleanKeyFrame KeyTime="0:0:1" Value="False"/> 
         </BooleanAnimationUsingKeyFrames> 
        </Storyboard> 
       </BeginStoryboard> 
      </DataTrigger.ExitActions> 
     </DataTrigger> 

     <Trigger Property="IsMouseOver" Value="True"> 
      <Trigger.EnterActions> 
       <PauseStoryboard BeginStoryboardName="ClosePopupStoryBoard" /> 
      </Trigger.EnterActions> 
      <Trigger.ExitActions> 
       <PauseStoryboard BeginStoryboardName="OpenPopupStoryBoard"/> 
       <ResumeStoryboard BeginStoryboardName="ClosePopupStoryBoard" /> 
      </Trigger.ExitActions> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

Затем, когда вы хотите использовать его, вы бы писать разметки похожее на это (обратите внимание, связывание для PlacementTarget):

<TextBlock x:Name="TargetControl" Text="Hover over me!" /> 
<Popup PlacementTarget="{Binding ElementName=TargetControl}" Style="{StaticResource TooltipPopupStyle}"> 
    <Border BorderBrush="Red" BorderThickness="1" Background="White"> 
     <TextBlock Text="This is a Popup behaving somewhat like the tooltip!" Margin="10" /> 
    </Border> 
</Popup> 
Смежные вопросы