지연된 WPF 팝업을 어떻게 열 수 있습니까?
-
20-09-2019 - |
해결책 3
우선 ...이 답변에 대한 크레딧은 에릭 버크. 그 대답했다 이 질문은 WPF 제자 그룹에 게시되었습니다. 나는이 답변을 stackoverflow에도 넣는 것이 유용 할 것이라고 생각했다.
기본적으로, 당신은 별개의 부울 킬키 프레임으로 팝업의 Isopen 속성을 애니메이션해야합니다.
다음 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을 마우스 위에 트리거하는 것과 그와 같이 확인란을 확인하는 것입니다. 팝업을 만들려고 시도하면 툴팁이 조금 비슷합니다.
다른 팁
다음과 같은 방식으로 팝업에 적용 할 스타일을 만들 수 있습니다.
<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>
그런 다음 사용하려면 마크 업을 작성할 때마다 다음과 비슷한 마크 업을 씁니다 (배치의 바인딩에주의하십시오).
<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>
CPLOTTS가 붙여 넣은 답변은 양호하지만 귀하의 경우에 애니메이션이 Isopen 속성에 부착되어 효과적으로 제자리에 고정되어 직접 속성 설정, 바인딩 및 기타 방법을 통해 변경되는 것을 방지하기 때문에 귀하의 경우에 적용되지 않을 수 있습니다. 이로 인해 코드 사용 방식에 따라 코드와 함께 사용하기가 어려울 수 있습니다.
이 경우 지연 후 팝업을 열고 싶을 때 Dispatchertimer를 시작하는 것으로 전환합니다.
_popupTimer = new DispatcherTimer(DispatcherPriority.Normal);
_popupTimer.Interval = TimeSpan.FromMilliseconds(100);
_popupTimer.Tick += (obj, e) =>
{
_popup.IsOpen = true;
};
_popupTimer.Start();
툴팁과 같은 동작의 경우 마우스 센터에서 수행 할 수 있습니다. 어떤 이유로 팝업 개구부를 취소하려면 (예 : 마우스가 팝업이 나타나기 전에 컨트롤을 떠나는 경우), 그냥 :
_popupTimer.Stop();
업데이트
주석에 cplotts가 멍청한 것처럼, 당신은 또한 설정하고 싶을 것입니다 _popup.IsOpen = false
Mouseleave 이벤트의 일부 상황에서는 컨트롤과 팝업 사이의 마우스 입력 / 출구 이벤트를 처리하기위한 논리에 따라. 보통 맹목적으로 설정하고 싶지 않다는 점에 유의하십시오. IsOpen=false
모든 Mouseleave 이벤트에서 팝업이 나타날 때 그렇게 할 수 있기 때문입니다. 이것은 어떤 상황에서는 깜박 거리는 팝업으로 이어질 것입니다. 그래서 당신은 거기에 약간의 논리가 필요합니다.
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();
}
마우스가 끝나는 한 팝업이 열려 있도록이 솔루션의 XAML을 확장 할 수 있습니다. 그런 다음 자동으로 사라집니다.
샘플을 다음과 같이 수정했습니다.
- 0.5 초 후에 Isopen을 False로 설정하는 "ClosePopop"애니메이션을 만듭니다. 나는 이것을 두 번 사용하기 때문에 이것을 자원으로 만들었습니다.
- Control의 ISMouseOver 트리거의 경우 ClosePopup 애니메이션을 시작하는 종료를 추가하십시오. 이를 통해 사용자는 마우스가 팝업을 닫기 전에 팝업 위로 이동할 수 있습니다. 나는이 애니메이션을 "bxb"라고 명명했습니다.
- 팝업의 ISMouseOver 속성에 트리거를 추가하십시오. 마우스 오버에서는 원래 "BXB"ClosePopup 애니메이션을 중지하고 제거하지 마십시오. 이것은 팝업을 보인다. 여기서 애니메이션을 제거하면 팝업이 닫히게됩니다.
- 팝업의 마우스 아웃에서 새로운 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>