2010-01-12 28 views

Trả lời

8

Trước hết ... tín dụng cho câu trả lời này sẽ chuyển đến Eric Burke. Ông answered câu hỏi này được đăng trong nhóm các môn đệ WPF. Tôi nghĩ rằng nó sẽ hữu ích để đưa câu trả lời này ra trên StackOverflow quá.

Về cơ bản, bạn cần tạo hiệu ứng thuộc tính IsOpen của cửa sổ bật lên bằng với DiscreteBooleanKeyFrame.

Check-out XAML sau (có thể dễ dàng dán vào Kaxaml này hay cách khác tiện ích chỉnh sửa XAML lỏng):

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

Xin lưu ý rằng tôi sửa đổi giải pháp ban đầu của mình một chút ... để kích hoạt ISOpen trên chuột so với kiểm tra CheckBox như ông đã có nó. Tất cả trong nỗ lực để làm cho Popup cư xử một chút như ToolTip.

10

Câu trả lời cplotts dán là tốt nhưng có thể không áp dụng trong trường hợp của bạn bởi vì nó rời khỏi hoạt ảnh gắn liền với tài sản IsOpen, hiệu quả khóa nó tại chỗ và ngăn không cho nó bị thay đổi thông qua thiết lập thuộc tính trực tiếp, ràng buộc và các cách khác . Điều này có thể gây khó khăn cho việc sử dụng với mã của bạn, tùy thuộc vào cách bạn đang sử dụng nó.

Nếu đúng như vậy, tôi sẽ chuyển sang bắt đầu một DispatcherTimer khi bạn muốn mở một cửa sổ bật lên sau khi một số chậm trễ, như thế này:

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

Đối với một hành vi ToolTip-như thế này có thể được thực hiện trên MouseEnter . Nếu bạn muốn hủy bỏ việc mở cửa sổ bật lên vì một lý do (chẳng hạn như nếu chuột rời khỏi kiểm soát trước khi popup xuất hiện), chỉ cần:

_popupTimer.Stop(); 

Cập nhật

Như cplotts obseved trong các bình luận, bạn cũng sẽ muốn đặt _popup.IsOpen = false trong một số trường hợp trong sự kiện MouseLeave, tùy thuộc vào logic của bạn để xử lý các sự kiện nhập/thoát chuột giữa điều khiển của bạn và cửa sổ bật lên. Lưu ý rằng bạn thường không muốn đặt một cách mù quáng IsOpen=false trên mọi sự kiện MouseLeave, vì nó có thể làm như vậy khi cửa sổ bật lên xuất hiện trên đó. Điều này sẽ trong một số trường hợp dẫn đến một popup nhấp nháy. Vì vậy, bạn sẽ cần một số logic ở đó.

+0

Điểm tốt ... và ý tưởng hay. Bạn cũng có thể muốn xóa giá trị IsOpen trong MouseLeave trong giải pháp trên. – cplotts

+0

Có thể bạn sẽ muốn làm điều này, nhưng cẩn thận. Tôi sẽ cập nhật câu trả lời của mình để giải thích ý tôi là gì. –

+0

Ray, cảm ơn rất nhiều! Đây chính là chức năng mà tôi cần. – 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

Mặc dù câu trả lời của bạn không trả lời được câu hỏi, nhưng thực tế là bạn thường muốn ẩn đầu công cụ sau một thời gian. Điều cần lưu ý. – cplotts

0

Bạn có thể mở rộng XAML cho giải pháp này để cửa sổ bật lên vẫn mở miễn là chuột kết thúc, sau đó biến mất tự động.

tôi sửa đổi mẫu như sau:

  1. Tạo một "ClosePopop" hoạt hình mà đặt ISOpen False sau 0,5 giây. Tôi đã tạo một tài nguyên này vì nó được sử dụng hai lần.
  2. Đối với trình kích hoạt IsMouseOver của điều khiển, hãy thêm Hành động Exit khởi động hoạt ảnh ClosePopup. Điều này cho phép người dùng có cơ hội di chuyển chuột qua cửa sổ bật lên trước khi nó đóng. Tôi đã đặt tên hoạt ảnh này là "bxb"
  3. Thêm Trình kích hoạt vào thuộc tính IsMouseOver của cửa sổ bật lên. Khi di chuột qua, dừng (nhưng không xóa) hoạt ảnh gốc "bxb" ClosePopup. Điều này để lại popup hiển thị; xóa hoạt ảnh ở đây sẽ làm cho cửa sổ bật lên đóng lại.
  4. Trên cửa sổ bật lên của cửa sổ bật lên, hãy bắt đầu hoạt ảnh ClosePopup mới rồi xóa hoạt ảnh "bxb". Bước cuối cùng là rất quan trọng bởi vì nếu không, hình ảnh động "bxb" đầu tiên dừng lại sẽ giữ cho cửa sổ bật lên mở.

Phiên bản này chuyển màu xanh lam khi chuột kết thúc để bạn có thể xem chuỗi sự kiện với 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

Bạn có thể tạo một phong cách được áp dụng cho các Popup theo cách sau:

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

Sau đó, bất cứ khi nào bạn muốn sử dụng nó, bạn sẽ viết đánh dấu tương tự như sau (chú ý các ràng buộc cho Mục tiêu Vị trí):

<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> 
Các vấn đề liên quan