Pregunta

Simplemente quiero abrir el emergente con un retraso, como una especie de información sobre herramientas.

¿Cómo puedo lograr esto?

Y, por cierto, Popup.PopupAnimation = PopupAnimation.Fade ... se desvanece en demasiado rápido. Quiero al menos medio segundo en ese país.

¿Fue útil?

Solución 3

En primer lugar ... el mérito de esta respuesta va a Eric Burke . Él href="http://groups.google.com/group/wpf-disciples/browse_frm/thread/32f1131129d5bf00?tvc=1" respondió esta misma pregunta publicada en el WPF grupo de discípulos. Pensé que sería útil poner esta respuesta cabo en StackOverflow también.

Básicamente, lo que necesita para animar la propiedad IsOpen de la ventana emergente con un DiscreteBooleanKeyFrame.

Comprobar 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 activar el puntero del ratón sobre IsOpen en comparación con marcar la casilla como lo había hecho él. En el intento de hacer emergente comporta un poco como información sobre herramientas.

Otros consejos

Puede crear un estilo que se aplicará 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>

A continuación, cada vez que desee utilizarlo, podría escribir marcado similar a este (nótese la unión por 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>

Los cplotts respuesta pegados es bueno, pero no se apliquen en su caso, ya que deja la animación adjunta a la propiedad IsOpen, cerrando de manera efectiva en su lugar y evitando que pueda ser cambiado mediante el ajuste directo propiedad, la unión, y otras formas. Esto puede hacer que sea difícil de usar con su código, dependiendo de cómo usted lo está utilizando.

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

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

Para una información sobre herramientas comportamiento similar a 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();

Actualizar

Como cplotts o dedos en el comentario, usted también desee establecer _popup.IsOpen = false en algunas situaciones en caso MouseLeave, dependiendo de su lógica para manejar el ratón entrar eventos / salida entre el control y la ventana emergente. Tenga en cuenta que por lo general no desea establecer ciegamente IsOpen=false en cada caso MouseLeave, ya que puede hacerlo cuando la ventana emergente aparece sobre ella. Esto en algunos casos conducir a una ventana emergente parpadeo. Por lo que tendrá algo de lógica allí.

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();
}

Se puede extender el XAML para esta solución por lo que las estancias emergentes abren siempre y cuando el ratón está sobre ella, y luego desaparece automáticamente.

he modificado la muestra como sigue:

  1. Crea una animación "ClosePopop" que establece IsOpen a Falso después de 0,5 segundos. Hice este recurso porque se usa dos veces.
  2. Para IsMouseOver gatillo del control, añadir una ExitAction que inicia la animación ClosePopup. Esto da al usuario la oportunidad de mover el puntero del ratón sobre la ventana emergente antes de que cierre. Nombré esta animación "bxb"
  3. Añadir un disparador para la propiedad IsMouseOver de la ventana emergente. Por encima del ratón, deje de (pero no quite) el "bxb" animación ClosePopup originales. Esto deja la ventana emergente visible; la eliminación de la animación aquí hará que se cierre el popup.
  4. En mouseout de la ventana emergente, se inicia una nueva animación ClosePopup luego retire la animación "bxb". El último paso es fundamental, porque de lo contrario la primera, se detuvo la animación "bxb" mantendrán la ventana emergente abierta.

Esta versión resulta el emergente azul, mientras que el ratón 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>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top