【发布时间】:2020-07-17 20:12:07
【问题描述】:
我有一个SizeChangedEventHandler,它会在每次窗口宽度发生变化时设置窗口的位置。 (如果窗口变为 100 宽,其Left 属性将设置为距屏幕右边缘 100,因此窗口始终与屏幕右边缘对齐。)
使宽度发生变化的是按钮的“可见性”在“可见”和“折叠”之间切换,在我的代码隐藏中使用 Binding 到布尔值和 BooleanToVisibilityConverter(全部演示如下)。
问题是,似乎是根据按钮消失之前的宽度而不是之后来计算位置。这使得窗口不会按照需要与屏幕的右边缘对齐。宽度为 80 时距离为 100,宽度为 100 时距离为 80。
<!-- MainWindow.xaml -->
<Window
x:Class="blah.MainWindow"
WindowStyle="None"
ResizeMode="NoResize"
Topmost="True"
SizeToContent="WidthAndHeight"
...
>
<Grid>
<WrapPanel Margin="3,0,3,3">
// IF is my shortened name for BooleanToVisibilityConverter
// In an <Application.Resources> I have <BooleanToVisibilityConverter x:Key="IF" />
<StackPanel Visibility="{Binding showThing, Converter={StaticResource IF}}">
<Button />
</StackPanel>
<Button />
<Button />
<Button />
<Button Click="handleClick" />
</WrapPanel>
</Grid>
</Window>
然后是它的代码隐藏
// MainWindow.xaml.cs
namespace blah
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private bool _showThing = false;
public bool showThing
{
get { return _showThing; }
set { _showThing = value; this.OnPropertyChanged(); }
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
this.Loaded += new RoutedEventHandler(this.setPosition_EventHandler);
this.SizeChanged += new SizeChangedEventHandler(this.setPosition_EventHandler);
}
private void setPosition_EventHandler(object sender, RoutedEventArgs e)
{
Rect desktopWorkingArea = SystemParameters.WorkArea;
this.Left = desktopWorkingArea.Right - this.Width;
this.Top = desktopWorkingArea.Bottom - this.Height;
}
private void handleClick(object sender, RoutedEventArgs e)
{
showThing = !showThing;
}
}
}
其他尝试
showThing 在单击右键时正确设置,左键正确折叠然后可见,setPosition_EventHandler 每次都被调用,因此窗口重新定位。只是它重新定位,好像按钮的可见性与其应有的可见性相反。
我尝试添加一个与setPosition_EventHandler 相同的setPosition,并在showThing 的设置器中调用它:
set { _showThing = value; this.OnPropertyChanged(); setPosition(); }
但它似乎仍然发生在属性更改导致按钮的可见性切换并因此改变窗口宽度之前。
有谁知道我如何确保尺寸更改事件处理程序确实发生在之后由于按钮被折叠而宽度发生了变化?
【问题讨论】:
-
The problem is, it appears that the position is being calculated based on the width before the button disappears, instead of after.你能解释一下before the button disappears的意思吗,上面的代码没有用按钮做任何事情。您是否也尝试过将按钮的可见性绑定设置为与堆栈面板相同? -
是的,当然。请参阅
StackPanel和Visibility="..."。它里面有一个Button,这就是占用空间的地方。从技术上讲,我可以说“StackPanel 消失了”。 -
感谢您的评论。问题是,由于调度程序,绑定实际上比 Windows 消息发生晚。简而言之,处理 UI 的消息将在绑定发生之前发生;你无法控制这个。你必须做一些古怪的添加/删除处理程序等。
-
啊,有趣,谢谢。那么有没有更合适的地方来运行
setPosition,而不是像现在这样运行SizeChangedEventHandler?这样按钮消失或重新出现后,然后计算并设置位置。 -
您也许可以尝试
LayoutUpdated或IsVisibleChanged事件并在那里处理位置;此事件是控件的一部分。
标签: c# wpf xaml data-binding