簡體   English   中英

自動定位窗口-WPF

[英]Auto Position Window - WPF

我創建了一個窗口,禁用了邊框並設置了SizeToContent =“ Height”。

xaml:

<Window Title="info" Width="350" ResizeMode="NoResize" WindowStyle="None" Opacity="1" Background="{x:Null}" AllowsTransparency="True" SizeToContent="Height">
   <Grid>
     <StackPanel Name="maingrid" Background="AliceBlue">
     </StackPanel>
   </Grid>
</Window>

當我打開此窗口時,將其放置在右下方屏幕中:

private void setposition()
{
   var primaryMonitorArea = SystemParameters.WorkArea;
   this.Left = primaryMonitorArea.Right - this.Width;
   this.Top = primaryMonitorArea.Bottom - this.Height;
}

有時我嘗試將孩子添加到maingrid ,然后重新定位它,因為Height已更改:

Border brd = new Border();
DockPanel.SetDock(brd, Dock.Top);
brd.Margin =new System.Windows.Thickness(0,5,0,0);
DockPanel dpanel = new DockPanel();
System.Windows.Controls.Label header = new System.Windows.Controls.Label();
header.Content = "test";
DockPanel.SetDock(header, Dock.Top);
dpanel.Children.Add(header);
brd.Child = dpanel;
maingrid.Children.Add(brd);
setposition();
System.Windows.Forms.Timer tmer = new System.Windows.Forms.Timer();
tmer.Tick += (sender, e) => timertick(brd, tmer);
tmer.Interval = 5 * 1000;
tmer.Enabled = true;

之后,將窗口位置隨機放置在垂直平面上。 5秒后,我破壞了邊框並嘗試重新定位窗口

private void timertick(Border brd, System.Windows.Forms.Timer timer)
{
  maingrid.Children.Remove(brd);
  timer.Enabled = false;
  setposition();
  timer.Dispose();         
}

垂直位置又有一些奇怪的價值。

在屏幕上的位置:

屏幕上的位置

您能否更精確地指定您的期望並嘗試表達您的問題?

如果要定位窗口,為什么不使用WindowStartupLocation

將WindowStartupLocation設置為Manual可使窗口根據其Left和Top屬性值定位。 如果未指定Left或Top屬性,則它們的值由Windows確定。 設置CenterScreen可使窗口位於包含鼠標光標的屏幕中央。

將WindowStartupLocation設置為CenterOwner會導致一個窗口位於其所有者窗口的中心(請參見Owner)(如果已指定)。 所有者窗口可以是另一個WPF窗口,也可以是非WPF窗口。

MSDN源碼

在調用setposition();的地方setposition(); 窗口大小尚未實現,要獲得實際大小,最簡單的方法是通過將操作放入調度程序隊列中來等待渲染。

考慮以下示例:

public MainWindow()
{
    InitializeComponent();
    Loaded += (s, e) => Title = $"{ActualHeight}"; // 39
    var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1), IsEnabled = true };
    timer.Tick += (s, e) =>
    {
        stackPanel.Children.Add(new TextBlock { Text = "123", Width = 200, Height = 20 });
        Title = $"{ActualHeight}"; // 39, 59, 79 ... wrong
        // below is correct way, displays 59, 79 ...
        //Dispatcher.Invoke(() => Title = $"{ActualHeight}", DispatcherPriority.Render);
    };
}

在這里,我有一個窗口,該窗口的大小適合內容並具有stackPanel

<Window SizeToContent="Height" Width="200" ...>
    <StackPanel x:Name="panel" />
</Window>

計時器每秒鍾向其添加新的TextBlock

現在,如果我嘗試像這樣更新Title ,那么ActualHeight仍然是舊的,在第一次更新后,第一個值是39 ,這是錯誤的(應該是20 + 39 = 59 )。 發生這種情況是因為添加子代不會立即重新計算所有內容和渲染。 否。相反,所有此類操作(度量,排列和渲染)都通過調度程序排入隊列,並在一段時間后發生 WPF就是這樣工作的。

為了解決這個問題,我可以簡單地告訴“請在渲染后執行”

Dispatcher.Invoke(() => ..., DispatcherPriority.Render);

我發現maingrid.ActualHeight在渲染窗口之前具有實際高度,然后執行以下操作:

this.Top = primaryMonitorArea.Bottom - maingrid.ActualHeight;

它的工作正常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM