Prevent WPF window flicker

夙愿已清 提交于 2019-12-18 08:53:26

问题


I've got a borderless WPF window that needs to be able to hide one of its controls and shrink the window at the same time.

The problem is that it looks terrible.

Here's what I am doing now:

private void btnShowHideTopBar_Click(object sender, RoutedEventArgs e)
{
    if (commandTopHide == true)
    {
        txtblkShowHideTopBar.Text = "Show Top Bar";
        commandTopHide = false;
        myWindow.Left = 1100;
        myWindow.Width = 180;
        RSide.Width = new GridLength(0, GridUnitType.Pixel);
    }
    else if (commandTopHide == false)
    {
        txtblkShowHideTopBar.Text = "Hide Top Bar";
        commandTopHide = true;
        myWindow.Left = 1030;
        myWindow.Width = 250;
        RSide.Width = new GridLength(70, GridUnitType.Pixel);
    }
}

And here is what it looks like in slow motion:

To correct this, I have tried a few things. Each of which apparently only apply to Winforms.
For example, I followed this blog post at Bee Eee to disable drawing and 'lock window update' to no avail.

I've also tried overriding the WM_PAINT message as seen in this post but I got stuck on what to do with the message once I catch it. The line base.WndProc(ref msg); throws the error "'System.Windows.Window' does not contain a definition for 'WndProc'"

Granted, that code was for Winforms and I am using the hwndSource.AddHook method as described in How to handle WndProc messages in WPF?)...



My xaml is fairly massive due to a my custom buttons, so I'll leave that out. Here is what's left:

<Window x:Name="myWindow" x:Class="myNamespace.myWindowClass"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
    Title="WiMan" Height="210" Width="250" ResizeMode="NoResize" WindowStyle="None" MinWidth="180" 
    MinHeight="210" MaxWidth="250" MaxHeight="210" Left="1030" Top="66" Loaded="ControlBoxLoadEvent" 
    Icon="pack://siteoforigin:,,,/Resources/App.ico" Closing="MainWindowIsClosing" Foreground="White" 
    Background="{x:Null}" AllowsTransparency="True">
<Window.Resources>
    <ControlTemplate ...stuff I left out.. > lots of stuff... </ControlTemplate>
</Window.Resources>
<Grid x:Name="MainWindowGrid" RenderTransformOrigin="0.5,0.5">
    <Grid.Background>
        <LinearGradientBrush EndPoint="160,240" StartPoint="160,-20" MappingMode="Absolute">
            <LinearGradientBrush.RelativeTransform>
                <TransformGroup>
                    <ScaleTransform CenterY="0.5" CenterX="0.5" ScaleY="1" ScaleX="1"/>
                    <SkewTransform AngleY="0" AngleX="0" CenterY="0.5" CenterX="0.5"/>
                    <RotateTransform Angle="-4.764" CenterY="0.5" CenterX="0.5"/>
                    <TranslateTransform/>
                </TransformGroup>
            </LinearGradientBrush.RelativeTransform>
            <GradientStop Color="#FF1B1B1B" Offset="1"/>
            <GradientStop Color="#7FC3C3C3"/>
        </LinearGradientBrush>
    </Grid.Background>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Name="RSide" Width="70"/>
        <ColumnDefinition Width="84*"/>
        <ColumnDefinition Width="83*"/>
    </Grid.ColumnDefinitions>
    <Button x:Name="btnShowHideTopBar" FontFamily="Arial Rounded MT Bold" FontSize="18" Click="btnShowHideTopBar_Click" 
      Template="...the stuff I left out..." Foreground="White" Background="{x:Null}" BorderBrush="{x:Null}" Margin="2" Grid.Row="1" Grid.Column="1">
        <TextBlock x:Name="txtblkShowHideTopBar" TextWrapping="Wrap" Text="Hide Topbar" TextAlignment="Center"/>
    </Button>
    <Button x:Name="btnShowHideSideBar" Grid.Column="2" Grid.Row="1" FontFamily="Arial Rounded MT Bold" FontSize="18" Click="eventHideShowSideBar_Click" 
     Template="...the stuff I left out..." Foreground="White" Background="{x:Null}" BorderBrush="{x:Null}" Margin="2">
        <TextBlock x:Name="txtblkShowHideSideBar" TextWrapping="Wrap" Text="Hide Sidebar" TextAlignment="Center"/>
    </Button>
    <Button Content="Configure" Click="btnConfigure_Click" FontFamily="Arial Rounded MT Bold" FontSize="18" 
     Template="...the stuff I left out..." Foreground="White" Background="{x:Null}" BorderBrush="{x:Null}" Margin="2" Grid.ColumnSpan="2" Grid.Column="1"/>
    <Grid Grid.RowSpan="2">
        <Grid.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF3C8AE8" Offset="0"/>
                <GradientStop Color="#FF032440" Offset="1"/>
            </LinearGradientBrush>
        </Grid.Background>
    </Grid>
    <Button x:Name="btnScrollLeft" Content="R Side" Click="RSideScrollButton_Click" FontFamily="Arial Rounded MT Bold" FontSize="18" 
      Template="...the stuff I left out..." Foreground="White" Background="{x:Null}" BorderBrush="{x:Null}" Margin="3,2,3,3" Grid.RowSpan="2"/>
</Grid>

@Walt Ritscher, I don't know about 'hiding' the column, I'm just setting it's width to 0. But the bigger problem seems to be that I need to resize and reposition the window that contains it.



@ErnodeWeerd, I've implemented a stopwatch as you can see here:

    Stopwatch s = new Stopwatch();
    string a; string b; string c; 

    s.Start();
    myWindow.Left = 1100;
    s.Stop(); a = s.Elapsed.ToString(); s.Reset();

    s.Start();
    myWindow.Width = 180;
    s.Stop(); b = s.Elapsed.ToString(); s.Reset();

    s.Start();
    RSide.Width = new GridLength(0, GridUnitType.Pixel);
    s.Stop(); c = s.Elapsed.ToString(); s.Reset();

    MessageBox.Show(a + Environment.NewLine +
            b + Environment.NewLine +
            c + Environment.NewLine);

This is the result:


回答1:


You can use a transparent window (AllowTransparency = True) with a grid, then when your control needs to be hidden you can set the visibility of the control to collapsed. There will be no flickering and no moving of the window but there won't be anything there either so you will see throug as if you would have resized, moved your window.



来源:https://stackoverflow.com/questions/22563416/prevent-wpf-window-flicker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!