C# 如何在窗口中居中弹出窗口(Windows应用商店应用程序)
我有一个自定义弹出窗口(作为用户控件),我通过编程加载它。我不能使它在x轴上居中,只能在垂直方向上。弹出窗口不会添加到xaml文件中,而是添加到根窗口中C# 如何在窗口中居中弹出窗口(Windows应用商店应用程序),c#,xaml,windows-store-apps,C#,Xaml,Windows Store Apps,我有一个自定义弹出窗口(作为用户控件),我通过编程加载它。我不能使它在x轴上居中,只能在垂直方向上。弹出窗口不会添加到xaml文件中,而是添加到根窗口中 using System; using System.Collections.Generic; using System.IO; using System.Linq; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; us
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Windows;
using Windows.UI.Core;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace QSTLibrary.WIN8.Tools
{
public sealed partial class CustomProgressRingPopup : UserControl
{
public CustomProgressRingPopup()
{
this.InitializeComponent();
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
// Using a DependencyProperty as the backing store for Text. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(CustomProgressRingPopup),
new PropertyMetadata("", OnTextChanged));
public void OpenPopup()
{
this.ParentPopup.IsOpen = true;
}
public void ClosePopup()
{
this.ParentPopup.IsOpen = false;
}
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as CustomProgressRingPopup;
var newValue = e.NewValue as string;
if (instance != null && newValue != null)
{
instance.CustomTextBlock.Text = newValue;
}
}
private void OnPopupLoaded(object sender, RoutedEventArgs e)
{
this.ParentPopup.HorizontalOffset = (Window.Current.Bounds.Width - gdChild.ActualWidth) / 2;
this.ParentPopup.VerticalOffset = (Window.Current.Bounds.Height - gdChild.ActualHeight) / 2;
}
}
}
userControl xaml:
<UserControl
x:Class="QSTLibrary.WIN8.Tools.CustomProgressRingPopup"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:QSTLibrary.WIN8.Tools"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Popup x:Name="ParentPopup" HorizontalAlignment="Center" VerticalAlignment="Center" Loaded="OnPopupLoaded">
<Grid x:Name="gdChild" Height="auto" Width="auto" Background="Blue" Margin="20">
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ProgressRing x:Name="CustomProgressRing" Height="40" Width="40" IsActive="true" Grid.Column="0" Margin="20"/>
<TextBlock x:Name="CustomTextBlock" Height="auto" Width="auto" FontSize="25" Grid.Column="1" Margin="20"/>
</Grid>
</Popup>
</UserControl>
您可以在XAML文件中居中:
<Popup x:Name="ParentPopup" PlacementTarget="{Binding ElementName=MainPanel}" Placement="Center" />
我在cs文件中添加了弹出窗口的LayoutUpdate回调,现在可以工作了
private void OnLayoutUpdated(object sender, object e)
{
if(gdChild.ActualWidth == 0 && gdChild.ActualHeight == 0)
{
return;
}
double ActualHorizontalOffset = this.ParentPopup.HorizontalOffset;
double ActualVerticalOffset = this.ParentPopup.VerticalOffset;
double NewHorizontalOffset = (Window.Current.Bounds.Width - gdChild.ActualWidth) / 2;
double NewVerticalOffset = (Window.Current.Bounds.Height - gdChild.ActualHeight) / 2;
if (ActualHorizontalOffset != NewHorizontalOffset || ActualVerticalOffset != NewVerticalOffset)
{
this.ParentPopup.HorizontalOffset = NewHorizontalOffset;
this.ParentPopup.VerticalOffset = NewVerticalOffset;
}
}
以及XAML中的弹出窗口:
<Popup x:Name="ParentPopup" LayoutUpdated="OnLayoutUpdated">
我修改了Butzke的答案,使之更具普遍性:
<Popup PlacementTarget="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Placement="Center" />
在UWP Windows应用商店应用程序中定位一个
弹出窗口
,并不像可能的那样简单。下面是我最终如何解决它的。不要观察LayoutUpdated
事件(这可能导致布局循环),而是观察视图顶级元素的SizeChanged
事件,并使用此事件重新定位其中包含的弹出窗口
在本例中,我将对话框定位在窗口的中心,因此使用window.Current
。您还需要转换坐标,因为弹出窗口将根据布局中实际定义的弹出窗口
元素的位置使用自己的相对坐标系:
private void MyDialog_SizeChanged(object sender, SizeChangedEventArgs e) {
var transform = Window.Current.Content.TransformToVisual(_popup);
Point point = transform.TransformPoint(new Point(0, 0)); // gets the window's (0,0) coordinate relative to the popup
double hOffset = (Window.Current.Bounds.Width - this.ActualWidth) / 2;
double vOffset = (Window.Current.Bounds.Height - this.ActualHeight) / 2;
_popup.HorizontalOffset = point.X + hOffset;
_popup.VerticalOffset = point.Y + vOffset;
}
我发现错误:在类型“Popup”中找不到属性“PlacementTarget”。与“Placement”相同。@AlexandruCircus
PlacementTarget
是要居中的面板。主面板默认存在,但您可以在另一个面板中居中。好的,我理解。但似乎PlacementTarget属性无法应用于Popup元素,这是我从错误中理解的:“在类型'Popup'中找不到属性'PlacementTarget'。”此外,当我编写Placemen时,它无法在代码中自动完成。。。它应该向PlacementTarget提供自动完成建议该项目是一个Windows应用商店应用程序。可能PlacementTarget不适用于此类项目。我是C#,.NET的新手……我是java程序员您是否尝试过只使用Grid
而不使用Popup
?在OpenPopup()
方法中,您需要设置网格的可见性。如果您仅使用网格
“Window.Current.Bounds”导致我的应用程序崩溃,错误为“检测到布局周期。布局无法完成”。通过将其更改为我使用的顶级容器,您也不需要处理弹出窗口
的偏移属性。我还更改了(NewHorizontalOffset!=double.NaN&(ActualHorizontalOffset!=NewHorizontalOffset | | ActualVerticalOffset!=NewVerticalOffset))-以检查是否也发生了NaN。@DaveFriedel我们面临同样的问题,但无法实施您的建议。我们有一个弹出窗口,其中我们正在使用一个包含此代码的用户控件,我们应该如何着手解决该问题,以避免出现循环布局异常thrown@Teja-你能发布一个示例吗(我不喜欢这样问,因为这样做太复杂了),我建议替换“Window.Current.Bounds.Width”使用位于堆栈顶部的网格根或其他对象的名称。我发现“窗口”导致了我的问题,但如果我命名了一个包装对象,它会起作用。Windows似乎不希望您在LayoutUpdated
处理程序中调整影响属性的布局。我建议改为使用SizeChanged
事件,它似乎没有这个问题。还存在“检测到布局周期。布局无法完成”问题,但通过将新的水平和垂直偏移量转换为intThis解决了这个问题。这对WPF有效,但PlacementTarget和FindAncestor模式在uwp应用程序中不可用
private void MyDialog_SizeChanged(object sender, SizeChangedEventArgs e) {
var transform = Window.Current.Content.TransformToVisual(_popup);
Point point = transform.TransformPoint(new Point(0, 0)); // gets the window's (0,0) coordinate relative to the popup
double hOffset = (Window.Current.Bounds.Width - this.ActualWidth) / 2;
double vOffset = (Window.Current.Bounds.Height - this.ActualHeight) / 2;
_popup.HorizontalOffset = point.X + hOffset;
_popup.VerticalOffset = point.Y + vOffset;
}