Frage

Ich möchte einfach öffnen die WPF Popup mit einer Verzögerung, ein bisschen wie ein ToolTip .

Wie kann ich das erreichen?

Und, nebenbei bemerkt, Popup.PopupAnimation = PopupAnimation.Fade ... Blendungen zu schnell. Ich möchte mindestens eine halbe Sekunde drin.

War es hilfreich?

Lösung 3

Zunächst einmal ... der Kredit für diese Antwort geht auf Eric Burke . Er dieser Frage in der WPF geschrieben beantwortet Jünger-Gruppe. Ich dachte, es wäre nützlich, auch diese Antwort löscht auf Stackoverflow.

Grundsätzlich müssen Sie die IsOpen Eigenschaft des Popup animieren mit mit einem DiscreteBooleanKeyFrame.

Überprüfen Sie den folgenden XAML-out (die leicht eingefügt werden können in Kaxaml oder andere lose XAML-Bearbeitungsprogramm):

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

Bitte beachten Sie, dass ich seine ursprüngliche Lösung leicht modifizierte ... die IsOpen auf Maus auszulösen über im Vergleich zu dem Kontrollkästchens, wie er es hatte. bei dem Versuch, alle Popup verhalten sich ein wenig wie Quick-Info.

zu machen

Andere Tipps

Sie können einen Stil erstellen, um das Popup in der folgenden Art und Weise angewandt werden:

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

Dann, wenn Sie es verwenden möchten, würden Sie schreiben Markup ähnlich wie diese (Hinweis für die Placement die Bindung):

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

Die Antwort cplotts geklebt ist gut, aber kann in Ihrem Fall nicht anwendbar, weil es die Animation-Blätter auf der IsOpen Eigenschaft angebracht ist, wirksam in Position verriegelt und verhindern, dass es über eine direkte Eigenschaftseinstellung geändert wird, Binden und andere Wege. Dies kann es schwierig machen, mit Ihrem Code zu verwenden, je nachdem, wie Sie es verwenden.

Wenn das der Fall ist, würde ich wechseln einen DispatcherTimer zu starten, wenn Sie ein Popup mit einiger Verzögerung öffnen möchten, wie diese:

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

Für eine Quick-Info-ähnliches Verhalten dieser auf MouseEnter- getan werden könnte. Wenn Sie die Popup-Öffnung aus irgendeinem Grund (zB wenn die Maus verlässt die Steuerung vor dem Popup angezeigt) abzubrechen, nur:

_popupTimer.Stop();

Aktualisieren

Wie cplotts im Kommentar obseved, werden Sie auch auf Satz _popup.IsOpen = false in einigen Situationen wollen in dem Mouseleave-Ereignisse, abhängig von Ihrer Logik für den Umgang mit der Maus eingeben / Exit-Ereignisse zwischen Steuerung und dem Popup. Beachten Sie, dass Sie in der Regel wollen nicht blind Satz IsOpen=false auf jedem Mouseleave-Ereignis, weil es so tun kann, wenn das Popup erscheint darüber hinweg. Dies würde in einigen Situationen führen zu einem Flackern Popup. So können Sie sich eine gewisse Logik benötigen.

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

Sie können die XAML für diese Lösung erweitern, so dass die Popup bleibt so lange geöffnet, wie die Maus über sie, dann automatisch ausgeblendet wird.

modifizierte ich die Probe wie folgt:

  1. Erstellen Sie eine „ClosePopop“ Animation, die nach 0,5 Sekunden IsOpen auf False setzt. Ich habe dies eine Ressource, weil es zweimal verwendet wird.
  2. Für die IsMouseOver Auslöser Kontrolle, fügen Sie ein ExitAction, die die ClosePopup Animation beginnt. Dies gibt dem Benutzer die Möglichkeit, die Maus über das Popup zu bewegen, bevor es geschlossen wird. Ich nannte diese Animation "bxb"
  3. Fügen Sie einen Trigger an den IsMouseOver Eigenschaft des Popup. Mit der Maus darüber, stop (aber nicht entfernen) der ursprünglichen „bxb“ ClosePopup Animation. Dies lässt das Fenster sichtbar; die Animation Entfernen hier wird das Popup schließen machen.
  4. Auf der mouseout des Pop-up, startet eine neue ClosePopup Animation dann die „bxb“ Animation entfernen. Der letzte Schritt ist wichtig, da sonst die erste, gestoppt „bxb“ Animation das Popup geöffnet halten.

Diese Version macht den Pop blau, während die Maus über sie, so dass Sie die Abfolge der Ereignisse mit 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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top