2011-01-08 20 views

Trả lời

5

Như Andrei đã chỉ ra, hành vi này nằm sâu bên trong kiểm soát Popup và khó khắc phục. Nếu bạn sẵn sàng làm một số công việc nó có thể được thực hiện bằng cách thay đổi kích thước và dịch nội dung của cửa sổ bật lên khi nó đạt đến mép màn hình. Đối với mục đích của cuộc biểu tình, chúng tôi sẽ tập trung vào cạnh trái của màn hình.

Nếu chúng ta có một số XAML như thế này:

<Window ... 
     LocationChanged="Window_LocationChanged" 
     SizeChanged="Window_SizeChanged" 
     > 
    <Grid> 
     <Rectangle Name="rectangle1" Width="100" Height="100" Fill="Blue"/> 
     <Popup Name="popup1" PlacementTarget="{Binding ElementName=rectangle1}" IsOpen="True" Width="100" Height="100"> 
      <TextBlock Background="White" TextWrapping="Wrap" Width="100" Height="100"> 
       <TextBlock.Text>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</TextBlock.Text> 
      </TextBlock> 
     </Popup> 
    </Grid> 
</Window> 

và mã-đằng sau như thế này:

private void Window_LocationChanged(object sender, EventArgs e) 
{ 
    RefreshPopupPosition(); 
} 

private void Window_SizeChanged(object sender, SizeChangedEventArgs e) 
{ 
    RefreshPopupPosition(); 
} 

private void RefreshPopupPosition() 
{ 
    var upperLeft = rectangle1.PointToScreen(new Point(0, 100)); 
    var xOffset = Math.Min(0, upperLeft.X); 
    popup1.Width = xOffset + 100; 
    (popup1.Child as FrameworkElement).Margin = new Thickness(xOffset, 0, 0, 0); 
    popup1.HorizontalOffset += 1; 
    popup1.HorizontalOffset -= 1; 
} 

sau đó bằng cách tính toán rằng Popup sẽ tắt màn hình, chúng ta có thể làm giảm độ rộng của nội dung và cho nó một lề âm để phần được trên màn hình được cắt bớt thành những gì sẽ xuất hiện nếu Popup là để cho phép điều này.

Điều này sẽ phải được mở rộng để đối phó với tất cả bốn cạnh của màn hình và khả năng nhiều màn hình, nhưng nó chứng tỏ rằng cách tiếp cận này là hoàn toàn khả thi.

1

Tôi không nghĩ rằng có cách để làm điều này. Ít nhất là một cách sạch sẽ. Nếu bạn nhìn vào lớp Popup với Reflector, bạn sẽ tìm thấy phương thức UpdatePosition sẽ điều chỉnh vị trí của cửa sổ bật lên sao cho nó nằm giữa các giới hạn màn hình. Phương thức này được gọi từ nhiều nơi, từ On***Changed gọi lại (OnPlacementChanged, OnVerticalOffsetChanged, v.v.).

Nếu bạn thực sự muốn nhận chức năng này, bạn có thể có một cơ hội nhỏ để mở rộng lớp Popup, ghi đè một số siêu dữ liệu trên các thuộc tính đã đăng ký với số gọi On***Changed để UpdatePosition không bao giờ được gọi, tuy nhiên hầu hết mọi người sẽ xem xét làm điều này để được cái ác thuần túy, tôi không khuyên bạn nên nó.

0

Bạn có thể sử dụng điều khiển PrecisePopup từ thư viện JungleControls mã nguồn mở của tôi. Nó sẽ định vị cửa sổ bật lên chính xác như được chỉ định ngay cả khi điều đó có nghĩa là cửa sổ bật lên bị tắt một phần.

Nó có thể tự động chọn vị trí phù hợp nhất trong số các vị trí bạn xác định, nhưng nếu bạn chỉ cần một vị trí bật lên chính xác tương ứng với vị trí "Dưới cùng" của Cửa sổ bật lên tích hợp, bạn có thể làm như sau:

<jc:PrecisePopup PlacementTarget="{Binding ElementName=SomeTarget}" 
       IsOpen="{Binding IsOpen}"> 
    <jc:PrecisePopup.Placements> 
     <jc:PrecisePopupPlacement VerticalTargetAlignment="Bottom" /> 
    </jc:PrecisePopup.Placements> 
    <!-- Popup content here... --> 
</jc:PrecisePopup> 
-1

Bạn phải đặt cửa sổ bật lên và mục tiêu của nó trong bảng điều khiển Canvas để nó không đặt lại vị trí do vấn đề cạnh màn hình trong điều khiển bật lên.

  <Canvas> 
      <Rectangle Name="rectPopUp" Width="30" Height="30"/> 
      <Button Width="20" Height="20" Name="btnAppLauncher" Click="btnAppLauncher_Click" Margin="-5,-2,0,0"> 
       <Button.Content> 
        <Path Fill="White" Stretch="Uniform" Data="M16,20H20V16H16M16,14H20V10H16M10,8H14V4H10M16,8H20V4H16M10,14H14V10H10M4,14H8V10H4M4,20H8V16H4M10,20H14V16H10M4,8H8V4H4V8Z"></Path> 
       </Button.Content> 
      </Button> 
      <Popup Name="pnlAppLauncherPopup" PlacementRectangle="0,25,0,0" PlacementTarget="{Binding ElementName=btnAppLauncher}" Placement="Bottom" AllowsTransparency="True" PopupAnimation="Slide"> 
       <UniformGrid Name="pnlAppLauncher"> 
       </UniformGrid> 
      </Popup> 
     </Canvas> 

Vì toàn bộ đơn vị nằm trong bảng điều khiển canvas và hình chữ nhật vị trí được đặt bật lên sẽ hiển thị bên dưới hình chữ nhật.

+0

Giải pháp này không làm việc cho tôi. Khi di chuyển cửa sổ bật lên của tôi gần cạnh màn hình, nó sẽ tự định vị lại cho phù hợp với bất kể vùng chứa Canvas. Tôi đã thử nhắm mục tiêu vị trí ngang hàng cũng như sử dụng cha mẹ mặc định. – Brannon

0

không có cách nào vào khuôn khổ WPF đặt Popup ra khỏi màn hình, nhưng bạn có thể buộc vị trí cửa sổ bật lên bằng cách gọi "SetWindowPos" thông qua P/Invoke:

#region P/Invoke imports & definitions 

     private const int HWND_TOPMOST = -1; 
     private const int HWND_NOTOPMOST = -2; 
     private const int HWND_BOTTOM = 1; 
     private const int SWP_NOMOVE = 0x0002; 
     private const int SWP_NOSIZE = 0x0001; 
     private const int SWP_NOACTIVATE = 0x0010; 
     private const int GW_HWNDPREV = 3; 
     private const int GW_HWNDLAST = 1; 


    [DllImport("user32.dll", EntryPoint = "SetWindowPos")] 
     private static extern int SetWindowPos(IntPtr hWnd, int hwndInsertAfter, int x, int y, int cx, int cy, int wFlags); 

#endregion 

private void updateposition(Item item) 
     { 
      if (item.IsOpen) 
      { 
       IntPtr hwnd = ((HwndSource)PresentationSource.FromVisual(item.popup.Child)).Handle; 
       SetWindowPos(hwnd, 0, (int)item.WorkPoint.X, (int)item.WorkPoint.Y, (int)item.popup.Width, (int)item.popup.Height, SWP_NOSIZE | SWP_NOACTIVATE); 

      } 


     } 
Các vấn đề liên quan