2010-01-12 13 views

Respuesta

8

En primer lugar ... el mérito de esta respuesta es Eric Burke. Él answered esta misma pregunta publicada en el grupo Discípulos de WPF. Pensé que sería útil poner esta respuesta en StackOverflow también.

Básicamente, necesita animar la propiedad IsOpen del Popup con un DiscreteBooleanKeyFrame.

revisa el siguiente XAML (que puede ser fácilmente pegar en Kaxaml u otra utilidad de edición de XAML suelto):

<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> 

Tenga en cuenta que he modificado ligeramente su solución original ... para desencadenar la IsOpen al pasar el mouse o verificar el CheckBox como lo tenía. Todo en un intento de hacer que Popup se comporte un poco como información sobre herramientas.

10

La respuesta pegada es buena, pero puede no aplicarse en su caso porque deja la animación adjunta a la propiedad IsOpen, bloqueándola efectivamente en su lugar e impidiendo que se modifique mediante la configuración de propiedad directa, enlace y otras formas . Esto puede dificultar el uso con su código, dependiendo de cómo lo esté usando.

Si ese es el caso, me gustaría cambiar a partir de un DispatcherTimer cuando se quiere abrir una ventana emergente con cierto retraso, así:

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

Para un comportamiento sobre herramientas-como esto se podría hacer en MouseEnter . Si desea cancelar la apertura emergente por alguna razón (por ejemplo, si el ratón deja el control antes de que aparezca la ventana emergente), simplemente:

_popupTimer.Stop(); 

actualización

Como cplotts o dedos en el comentario, también querrá establecer _popup.IsOpen = false en algunas situaciones en el evento MouseLeave, dependiendo de su lógica para manejar los eventos de entrada/salida del mouse entre su control y la ventana emergente. Tenga en cuenta que generalmente no desea configurar a ciegas IsOpen=false en cada evento MouseLeave, porque puede hacerlo cuando aparezca la ventana emergente sobre él. En algunas situaciones, esto generaría una ventana emergente parpadeante. Entonces necesitarás algo de lógica allí.

+0

Buen punto ... y buena idea. Es posible que también desee borrar el valor de IsOpen en MouseLeave en la solución anterior. – cplotts

+0

Sí, es probable que desee hacer esto, pero con cuidado. Actualizaré mi respuesta para explicar a qué me refiero. –

+0

Ray, muchas gracias! Esta era exactamente la funcionalidad que necesitaba. – 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

Si bien su respuesta no responde en absoluto a la pregunta, sí revela el hecho de que a menudo desea ocultar la información sobre herramientas después de un tiempo. Algo para tener en cuenta. – cplotts

0

Puede extender el XAML para esta solución para que la ventana emergente permanezca abierta mientras el mouse esté sobre ella, luego desaparecerá automáticamente.

he modificado la muestra como sigue:

  1. crear una animación "ClosePopop" que establece IsOpen a Falso después de 0,5 segundos. Hice esto un recurso porque se usa dos veces.
  2. Para el desencadenante IsMouseOver del control, agregue una ExitAction que inicia la animación ClosePopup. Esto le da al usuario la oportunidad de mover el mouse sobre la ventana emergente antes de que se cierre. Llamé a esta animación como "bxb"
  3. Agregue un disparador a la propiedad emergente IsMouseOver. Al pasar el mouse, detenga (pero no elimine) la animación original de ClosePopup "bxb". Esto deja la ventana emergente visible; eliminar la animación aquí hará que la ventana emergente se cierre.
  4. En el mouseout de la ventana emergente, inicie una nueva animación de ClosePopup y luego elimine la animación "bxb". El último paso es crítico porque, de lo contrario, la primera animación detenida "bxb" mantendrá abierta la ventana emergente.

Esta versión convierte el pop en azul mientras el mouse está sobre ella para que pueda ver la secuencia de eventos con 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

Puede crear un estilo que debe aplicarse a la emergente de la siguiente manera:

<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> 

Entonces, cada vez que desee utilizarlo, podría escribir marcado similar a este (nótese la unión para el 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> 
Cuestiones relacionadas