Skip to content

[API Spec] TitleBar's Content Custom Drag Regions#10936

Open
vinnarayana-msft wants to merge 7 commits intomicrosoft:mainfrom
vinnarayana-msft:user/vinnarayana/titlebar-content-draggable/spec
Open

[API Spec] TitleBar's Content Custom Drag Regions#10936
vinnarayana-msft wants to merge 7 commits intomicrosoft:mainfrom
vinnarayana-msft:user/vinnarayana/titlebar-content-draggable/spec

Conversation

@vinnarayana-msft
Copy link

@vinnarayana-msft vinnarayana-msft commented Dec 29, 2025

This PR introduces an API specification for addressing custom TitleBar draggability issues. The proposal adds a new attached property, IsDragRegion, allowing developers to explicitly mark UI elements within TitleBar Content that should not participate in window dragging. By excluding interactive controls or specific regions, all remaining title bar areas behave predictably as draggable surfaces.

Fixes

PR Type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

Description

Custom title bar layouts often mix interactive elements—like buttons and search boxes—with non‑interactive visual elements. When these elements are arranged using containers such as Grid, StackPanel, or nested layouts, the system cannot reliably determine which parts of the TitleBar.Content should act as the draggable window surface. This can leave some areas unintentionally non‑draggable, resulting in inconsistent window movement.

To make dragging behavior predictable, developers need a simple way to exclude only the interactive elements from contributing to the drag surface, allowing the rest of the title bar to function as expected for window dragging. This proposal introduces an attached property to explicitly mark such elements, improving clarity and control in custom title bar designs.

This work is also part of the improvements tracked in #10421.

A lightweight and explicit API is therefore needed to let developers clearly mark non draggable regions within any TitleBar layout while keeping default behaviour unchanged.

Motivation and Context

Introduce a new attached property:

Developers can use the TitleBar.IsDragRegion attached property to indicate which UI elements in a custom title bar should not act as drag surfaces. Interactive controls are typically excluded from dragging, while all other non‑interactive areas of the title bar automatically function as draggable regions.

How Has This Been Tested?

  • I have performed a self-review of my own code
  • I have added tests to cover my changes

Screenshots (if appropriate):

@microsoft-github-policy-service microsoft-github-policy-service bot added the needs-triage Issue needs to be triaged by the area owners label Dec 29, 2025
@vinnarayana-msft
Copy link
Author

@microsoft-github-policy-service agree

@ghost1372
Copy link
Contributor

@vinnarayana-msft is there any plan to fix titlebar issues?
here you can find a list of titlebar issues:
microsoft/WindowsAppSDK#5250

@vinnarayana-msft vinnarayana-msft changed the title [API Spec] TitleBar's Content IsDraggable Property [API Spec] TitleBar's Content ExcludeFromDrag Property Dec 29, 2025
Copy link

@Zakariathr22 Zakariathr22 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest also using IsDragEnabled instead of ExcludeFromDrag because it avoids negative wording and follows common boolean naming rules.

@vinnarayana-msft
Copy link
Author

vinnarayana-msft commented Dec 31, 2025

I suggest also using IsDragEnabled instead of ExcludeFromDrag because it avoids negative wording and follows common boolean naming rules.

Thank you @Zakariathr22 for the suggestion. The intent behind using ExcludeFromDrag is that in custom TitleBar layouts, the entire content region effectively becomes draggable, and developers typically only need to mark interactive controls as not draggable. So the property acts as an opt‑out, not an opt‑in, which makes a negative‑form name more accurate for the underlying behavior.
That said, I’m open to considering alternative names that still convey this opt‑out pattern if there’s a clearer option.

@riverar
Copy link
Contributor

riverar commented Jan 5, 2026

Is there prior art for negative-form Boolean properties? I think it's more common to use positive Boolean properties. +1 to the suggested change here (from ExcludeFromDrag to IsDraggable or IsDragEnabled).

@riverar
Copy link
Contributor

riverar commented Jan 5, 2026

Microsoft Office allows dragging and Microsoft Teams does not. Which one is right?
image

image


### Keyboard Behaviour

This API does not introduce new keyboard interactions by itself; it influences pointer-driven window dragging. However, custom title bar content must still follow common keyboard accessibility expectations:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about touch?


Custom title bar layouts often combine interactive controls with non-interactive visual elements using containers like `Grid`, `StackPanel`, or nested structures. These layouts can unintentionally create gaps or regions whose drag behavior the framework cannot reliably infer. As a result, some title bar areas may unexpectedly become non-draggable, leading to inconsistent window movement.

To ensure predictable dragging behavior, developers need a way to explicitly mark UI elements that should **not** participate in window dragging—typically interactive controls. All remaining areas then function automatically as draggable regions. This proposal introduces the `TitleBar.ExcludeFromDrag` attached property to provide explicit, predictable control.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think ExcludeFromDrag should be renamed to IsDraggable or similar.

See also: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-type-members#names-of-properties

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on renaming it to be positive. Although, both IsDraggable and IsDragEnabled make it sound, to me, like the control itself is draggable. What about something like IsDragRegion? Sounds weird, but something in this vein.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with above comment.

@Jay-o-Way
Copy link
Contributor

Jay-o-Way commented Jan 8, 2026

So the property acts as an opt‑out, not an opt‑in

Irrelevant. It's a property, and if the default is true then so be it. A property should always have a neutral or positive phrasing.

Also, in my opinion, something like this should have been discussed and agreed upon, before opening a PR. Note that you are a Microsoft employee and therefore a professional level is inherently expected.

@vinnarayana-msft vinnarayana-msft changed the title [API Spec] TitleBar's Content ExcludeFromDrag Property [API Spec] TitleBar's Content Custom Drag Regions Jan 27, 2026
@pranav-gupta-msft
Copy link
Member

The PR Description, can also contain, "BugFix" as this is one of the pending bugs which we are fixing.

@Jay-o-Way
Copy link
Contributor

@pranav-gupta-msft how does a SPEC (documents for a new feature) fix an existing BUG? Those are two completely different things.

// Attached property used for per-element overrides
static DependencyProperty IsDragRegionProperty { get; };
static void SetIsDragRegion(DependencyObject element, Boolean value);
static Boolean GetIsDragRegion(DependencyObject element);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No sample for GetIsDragRegion. Is that because there are no real use-cases consuming it?

We mention that inability to differentiate False from omitted doesn't impede the framework because that uses ReadLocalValue(). Do we expect app code to ever check DragRegion via one or both avenues?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SAMPLE: Add example for GetIsDragRegion

- **High flexibility** (simple overrides where needed).
- **Consistent, accessible behavior** aligned with product expectations.

**XAML sample**

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Samples layout nit. The only markup snippet in "XAML sample" is one that doesn't use the new property. Is that because we don't encourage developers to ever set this vs. using the new default?

I'm not sure if it's intentional to demote the other samples to "Additional How‑To". Though this only matters if they will end up on different doc pages.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DISCUSSION: First example doesn't use new API. As default is changing, this example capture that hence not using new API.

We have examples for new API below.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should reword the document to say "We are making two changes. (1) Changing the default behavior for deciding which parts of the TitleBar can be used to drag. (2) Giving developer the ability to override the default behavior."

This "Problem example" should be titled "Changes to default behavior". It shows the markup, explains the existing problem with Column 1, and explains how the new behavior fixes it.

# TitleBar Draggability API Specification

# Background
Custom title bar layouts often combine interactive controls with non-interactive
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Custom title bar layouts often combine interactive controls with non-interactive
WinUI3 Title bar

All remaining areas then function automatically as draggable regions. This proposal introduces
the `TitleBar.ExcludeFromDrag` attached property to provide this explicit, predictable control.

This work is also related to **[#10421](https://github.com/microsoft/microsoft-ui-xaml/issues/10421)**.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue reference not required in API spec.

unexpectedly become non-draggable, leading to inconsistent window movement.

To ensure predictable dragging behavior, developers need a way to explicitly mark UI
elements that should **not** participate in window dragging—typically interactive controls.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add reasons why existing API aren't sufficient to compute draggable region. Why do we need new API for bridging gap between visually draggable and actually draggable region?

You can apply `IsDragRegion` to containers to include/exclude large UI areas (e.g., toolbars). Use it sparingly to avoid accidentally disabling drag for entire subtrees; prefer marking the minimum necessary element.

```xml
<StackPanel Orientation="Horizontal" TitleBar.IsDragRegion="False">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unclear if "Region" is the correct suffix since you don't apply it to a region; you apply it to an element.

Is this "IsDraggable"?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But what's draggable is the window, not the element.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about TitleBar.Included? True means "it's included in the title bar, you can drag with it." False means "it's not included in the title bar; we punched a hole to exclude it. You can't drag with it."

Copy link
Contributor

@riverar riverar Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Edit: Removed after some reflection.)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about TitleBar.Included? True means "it's included in the title bar, you can drag with it." False means "it's not included in the title bar; we punched a hole to exclude it. You can't drag with it."

I think that strays too far from how other attached properties are named. I like the idea of something as simple as Grid.Row and Canvas.ZIndex. IsDragRegion feels a little out of place, but from the suggestions I've seen it's the one I feel it makes the most sense.

I can't think of an existing bool attached property that we could use to compare.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this property isn't just about title bar dragging, but describes whether it is part of the title bar in general. E.g., if you right-click it, do you get a system menu? If you double-click it, does the window maximize?

Maybe <StackPanel TitleBar.IncludeInCaption="True"/>? or TitleBar.IncludeInTitleBar, or TitleBar.HitTestInclude

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it describes if the element is a drag region, and by extension if it's interactable. Maybe IsInteractionEnabled?

I was being an idiot: of course there are bool attached properties, such as ScrollViewer.IsHorizontalScrollChainingEnabled. Every bool attached property in ScrollViewer looks like Is[...]Enabled.

- **High flexibility** (simple overrides where needed).
- **Consistent, accessible behavior** aligned with product expectations.

**XAML sample**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DISCUSSION: First example doesn't use new API. As default is changing, this example capture that hence not using new API.

We have examples for new API below.

<StackPanel Orientation="Horizontal">
<TextBlock Text="Title"/>
<Grid>
<Button Content="Settings" TitleBar.IsDragRegion="False"/> <!-- Exclude -->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussion: Button is not good example for IsDragRegion example.

SAMPLE: Stack panel setting yes to drag region, but button overriding. Having SxS view of two cases will help.

<pre lang="xml">&lt;TitleBar&gt;
&lt;TitleBar.Content&gt;
&lt;TextBlock Text="My App" /&gt;
&lt;AutoSuggestBox TitleBar.IsDragRegion="True" /&gt;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DISCUSSION: Should it be boolean value? What will get return if value is not locally set?

AttachProperty always return local value?

The main area where defining a custom attached property differs from a custom dependency property is in how you define the accessors or wrappers. Instead of the using the wrapper technique described in Custom dependency properties, you must also provide static GetPropertyName and SetPropertyName methods as accessors for the attached property. The accessors are used mostly by the XAML parser, although any other caller can also use them to set values in non-XAML scenarios.

Reference: https://teams.microsoft.com/l/message/19:meeting_ZTYyODdkNjYtNmJmNi00N2NmLTg4ZmMtODRlZmNkYjVmZDNh@thread.v2/1770828647884?context=%7B%22contextType%22%3A%22chat%22%7D

If we walk up the tree, get API name need to change.

RECOMMEND: Follow up on get behavior if not locally defined.

// Attached property used for per-element overrides
static DependencyProperty IsDragRegionProperty { get; };
static void SetIsDragRegion(DependencyObject element, Boolean value);
static Boolean GetIsDragRegion(DependencyObject element);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SAMPLE: Add example for GetIsDragRegion

namespace Microsoft.UI.Xaml.Controls
{
// Attached property used for per-element overrides
static DependencyProperty IsDragRegionProperty { get; };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DISCUSSION: Should it be IncludeInDragRegion, IsIncludedInDragRegion?

We should choose name after solving get compute issue mentioned above.

RECOMMEND: Need to comeback after get API issue is resolved.


## Approaches Overview

In this approach the framework recursively traverses the visual tree and **excludes interactive controls from drag by default**. Developers can then **override** per element using `TitleBar.IsDragRegion`:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this different from the old behavior? All that the document says is that the old behavior " subtracts (or "punches holes" from) regions that should not initiate window dragging." But that's the same as the new behavior: The new behavior subtracts regions that should not initiate window dragging.

So what changed?

# API Details

```c#
namespace Microsoft.UI.Xaml.Controls
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only lists namespace. This should also show these inside the TitleBar class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-triage Issue needs to be triaged by the area owners

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Comments