How to resize a borderless window from top only?

2019-07-27 02:25发布

I am creating a WPF application and want my window to be borderless, and also possible to be resized only from the top.

What I have tried so far

  • I initially thought this would work:

    <Window x:Class="WpfApplication3.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Width="200" Height="150"
            WindowStyle="None"
            ResizeMode="CanResize"
            AllowsTransparency="True"
            BorderThickness="0,5,0,0"
            BorderBrush="Black">
        <Grid Background="Gray" />
    </Window>
    

    I do get a window with top border only, but I cannot resize it.

    enter image description here

  • Then I tried WindowChrome.ResizeGripDirection="Top" with ResizeMode="CanResizeWithGrip".

    <Window ...
            WindowStyle="None"
            ResizeMode="CanResizeWithGrip"
            AllowsTransparency="True"
            WindowChrome.ResizeGripDirection="Top"
            BorderThickness="0,5,0,0"
            BorderBrush="Black">
        ...
    </Window>
    

    This does not work either (unable to resize from top border), and the grip does not even appear on top. It stays on the bottom-right corner (I can resize with the grip, though).

    enter image description here

  • This answer seems like the answerer may initially have done this, but the code is unavailable.

  • This answer has a link to a blog post, I am not too eager to try it because I would like a solution without code behind.
  • And then there is this answer:

    • I get an error with this approach:

      <Window ...
              WindowStyle="None"
              ResizeMode="CanResizeWithGrip"
              AllowsTransparency="False">
          <Grid Background="Gray" />
          <Setter Property="WindowChrome.WindowChrome">
              <Setter.Value>
                  <WindowChrome CornerRadius="0"
                                GlassFrameThickness="1"
                                UseAeroCaptionButtons="False"/>
              </Setter.Value>
          </Setter>
      </Window>
      

      The property 'Content' is set more than once.

    • With code behind:

      <Window ...
              WindowStyle="None"
              ResizeMode="CanResize"
              AllowsTransparency="False">
          <Grid Background="Gray" />
      </Window>
      

      In constructor:

      WindowChrome chrome = new WindowChrome();
      chrome.CornerRadius = new CornerRadius(0);
      chrome.GlassFrameThickness = new Thickness(0, 1, 0, 0);
      chrome.UseAeroCaptionButtons = false;
      

      Which gives me:

      enter image description here

      And this could be resized from all directions. And I only want it to be able to resize from top. (Surprise: I did not even assign the new chrome object to anything. How did that work? That's another question I guess).


Question

How do I make a borderless window which can only be resized with the top border? (It's best if I can do this with only a top border whose color could be changed).

1条回答
叛逆
2楼-- · 2019-07-27 02:49

You may have success setting the WindowChrome.ResizeBorderThickness property to remove all borders except the top, e.g. ResizeBorderThickness="0, 5, 0, 0".

It may not be the cleanest way to achieve your result, but I've had some success adapting the answer here: http://www.eidias.com/blog/2014/1/27/restyle-your-window (it was the easiest way I found to get WindowChrome working):

Create a custom window style in a ResourceDictionary:

<ResourceDictionary x:Class="WpfApplication.WindowStyle"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Style x:Key="CustomWindowStyle" TargetType="{x:Type Window}">
        <Setter Property="WindowChrome.WindowChrome">
            <Setter.Value>
                <WindowChrome CaptionHeight="30"
                              CornerRadius="4"
                              GlassFrameThickness="0"
                              ResizeBorderThickness="0, 5, 0, 0"
                              UseAeroCaptionButtons="False" />
            </Setter.Value>
        </Setter>
        <Setter Property="Window.BorderThickness" Value="0, 5, 0, 0" /
    </Style>
</ResourceDictionary>

Reference the dictionary where required (I put it in App.xaml):

<Application x:Class="WpfApplication1.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:WpfApplication1"
         StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary Source="WindowStyle.xaml" />
    </Application.Resources>
</Application>

Reference the Style in the required Window:

<Window x:Class="WpfApplication1.MainWindow"
    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"
    xmlns:local="clr-namespace:WpfApplication1"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525"
    Style="{StaticResource ResourceKey=CustomWindowStyle}">
    <Grid>
    </Grid>    
</Window>

That should produce a window that looks like your final one, but can only be resized from the top (only the top resize handle can be grabbed).

查看更多
登录 后发表回答