Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Moving a WPF Window with a WindowStyle of None

, 14 Apr 2010 CC (Attr 3U)
Rate this:
Please Sign up or sign in to vote.
Moving a WPF Window with a WindowStyle of None

CustomWindow

In my previous post: Creating a Custom Window Style, I showed how to create a custom Style in WPF using WindowStyle.None and ResizeMode.NoResize. What bugged me about this approach was that you can't move the custom window, because you have no Window chrome to drag around the screen.

I read one article that took a really “hard core” approach and used interop to use the SendMessage, ReleaseCapture, and MouseMove methods, but this is a very Win32-oriented approach and in actual fact, WPF provides a much easier approach.

To enable a user to move your window from any area on that window (not necessarily just the title if you want to do something really different), you simply handle the MouseLeftButtonDown event for a UIElement on your window and call the DragMove method, as shown in the following code example:

private void title_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DragMove();
}

Hooking it Up to the Style

Having defined the look-and-feel in a reusable Style, we need a way of hooking up the MouseLeftButtonDown event and handling it in our Window class. Unfortunately, this is a little bit tricky. If the Style is defined in the XAML that defines your Window then you can simply add the event handler for the relevant UIElement as you would for any other element. However, putting your Style in with your actual Window doesn't give you a very reusable Style. Instead, give a fixed name to the element in your Style, such as PART_Title, and then get a reference to that element and hook the event in your Window class. Are you still with me?

The following XAML code example shows the named part in the Window Style.

<Style x:Key="MessageBox" TargetType="{x:Type Window}">
    ...
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Window}">
                <Border Background="{DynamicResource MessageBoxBackgroundBrush}"
                        BorderBrush="{DynamicResource MessageBoxBorderBrush}"
                        BorderThickness="1">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="30" />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Grid x:Name="PART_Title">
                            <Grid.Background>
                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="#FF214F18" Offset="0"/>
                                    <GradientStop Color="#FF20361C" Offset="1"/>
                                </LinearGradientBrush>
                            </Grid.Background>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition Width="30" />
                            </Grid.ColumnDefinitions>
                            <Label Style="{DynamicResource MessageBoxTitle}" 
				Content="{TemplateBinding Title}" />
                            <Button x:Name="PART_Close"
                                    Content="{DynamicResource CloseButtonPath}"
                                    Grid.Column="1"
                                    Style="{DynamicResource CloseButton}"
                                    Padding="4" />
                        </Grid>
                        <AdornerDecorator Grid.Row="1">
                            <ContentPresenter Content="{TemplateBinding Content}" 
				Margin="{TemplateBinding Margin}" />
                        </AdornerDecorator>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

All I've done from the previous version of the Style is to add an x:Name attribute with a value of PART_Title to the Grid that contains the title of the Window.

The following code example shows how to get a reference to that element and hook the mouse event in the CustomMessageBox class.

namespace CustomWindow
{
    /// <span class="code-SummaryComment"><summary>
</span>    /// Interaction logic for CustomMessageBox.xaml
    /// <span class="code-SummaryComment"></summary>
</span>    public partial class CustomMessageBox : Window
    {
        private MessageBoxResult _result = MessageBoxResult.None;
        private Button _close;
        private FrameworkElement _title;

        ...

        private void this_Loaded(object sender, RoutedEventArgs e)
        {
            this._close = (Button)this.Template.FindName("PART_Close", this);
            if (null != this._close)
            {
                if (false == this._cancel.IsVisible)
                {
                    this._close.IsCancel = false;
                }
            }

            this._title = (FrameworkElement)this.Template.FindName("PART_Title", this);
            if (null != this._title)
            {
                this._title.MouseLeftButtonDown += 
		new MouseButtonEventHandler(title_MouseLeftButtonDown);
            }
        }

        private void title_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DragMove();
        }

        ...
    }
}

Summary

So, if you want to enable window movement for custom styled windows, then you need to call the DragMove method from an event handler for the MouseLeftButtonDown event. In this example, the CustomMessageBox class provides that event handling. If you are using a Style that applies to multiple windows, then you will need to hook the mouse event in each class, or implement a base class that provides this functionality for you and inherit from that class.

As before, I've provided the (now updated) source code for the custom message box class.

<iframe style="border-right: #dde5e9 1px solid; padding-right: 0px; border-top: #dde5e9 1px solid; padding-left: 0px; padding-bottom: 0px; margin: 3px; border-left: #dde5e9 1px solid; width: 240px; padding-top: 0px; border-bottom: #dde5e9 1px solid; height: 66px; background-color: #ffffff" marginwidth="0" marginheight="0" src="http://cid-2ebcba238c071a49.skydrive.live.com/embedrowdetail.aspx/WPF/CustomMovableWindow.zip" frameborder="0" scrolling="no"></iframe>

This work is licensed under a Creative Commons Attribution By license.
<script type=""text/javascript""></script><script type=""text/javascript""></script><script type=""text/javascript""></script><script type=""text/javascript""></script><script language=""javascript"" src=""http://widgets.dzone.com/widgets/zoneit.js""></script>

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution 3.0 Unported License

Share

About the Author

Derek Lakin
Software Developer (Senior)
United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
GeneralVery useful PinmemberBGW5-Sep-13 21:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411022.1 | Last Updated 15 Apr 2010
Article Copyright 2009 by Derek Lakin
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid