wpf 强制布局更新

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16839057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:53:32  来源:igfitidea点击:

Forcing layout update

wpf

提问by David Daks

How to force the layout measurements update?

如何强制布局测量更新?

I have simplified layout I am problem with; when you click the button first time you get one measurement and on the second click different one.

我简化了我遇到的问题;当您第一次单击按钮时,您会得到一个测量值,第二次单击不同的测量值。

   private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        var w = mywindow.ActualWidth;
        gridx.Width = w;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        btn3.Width = 100;
        var w = mywindow.ActualWidth;
        gridx.Width = w - btn3.Width;
        InvalidateArrange();
        InvalidateMeasure();

        MessageBox.Show(btn1.ActualWidth.ToString());
    }

Window

窗户

<Window x:Class="resizet.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" Name="mywindow">

        <DockPanel HorizontalAlignment="Stretch" LastChildFill="False">
            <Grid HorizontalAlignment="Stretch" DockPanel.Dock="Left" Name="gridx">
                <Button HorizontalAlignment="Stretch" Content="btn in grid" Click="Button_Click" />
            </Grid>
        <Button Name="btn2" Content="btn2" Width="0" DockPanel.Dock="Right" HorizontalAlignment="Left"></Button>
        </DockPanel>
</Window>

回答by Daniel

This fixes the problem:

这解决了这个问题:

btn3.Width = 100;    
btn3.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
var w = mywindow.ActualWidth;
gridx.Width = w - btn3.Width;

with additional

加上额外的

private static Action EmptyDelegate = delegate() { };

回答by Vlad

Changing the Widthproperty must invalidate the layout on its own, you don't need to call InvalidateXXX()yourself.

更改Width属性必须自行使布局无效,您无需调用InvalidateXXX()自己。

The catch is that the layout is not updated immediately, but on the next iteration of the message loop. So the ActualWidthwill not be changed immediately.

问题是布局不会立即更新,而是在消息循环的下一次迭代中更新。所以ActualWidth不会立即更改。



If you want the Gridto resize automatically when the button width is increasing, why not use the layout management and put the both into different columns of an outer Grid?

如果您希望在Grid按钮宽度增加时自动调整大小,为什么不使用布局管理并将两者放入外部的不同列中Grid

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Grid x:Name="gridx"
          Grid.Column="0">
        <Button HorizontalAlignment="Stretch"
                Click="Button_Click"/>
    </Grid>
    <Button x:Name="btn2"
            Content="btn2"
            Width="0"
            Grid.Column="1"/>
</Grid>

And in code-behind

在代码隐藏中

private void Button_Click(object sender, RoutedEventArgs e)
{
    btn2.Width = 100;
}