[API Spec] TitleBar's Content Custom Drag Regions#10936
[API Spec] TitleBar's Content Custom Drag Regions#10936vinnarayana-msft wants to merge 7 commits intomicrosoft:mainfrom
Conversation
|
@microsoft-github-policy-service agree |
|
@vinnarayana-msft is there any plan to fix titlebar issues? |
Zakariathr22
left a comment
There was a problem hiding this comment.
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. |
|
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 |
|
|
||
| ### 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: |
|
|
||
| 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. |
There was a problem hiding this comment.
Think ExcludeFromDrag should be renamed to IsDraggable or similar.
There was a problem hiding this comment.
+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.
There was a problem hiding this comment.
Agree with above comment.
Irrelevant. It's a property, and if the default is 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. |
|
The PR Description, can also contain, "BugFix" as this is one of the pending bugs which we are fixing. |
|
@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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
SAMPLE: Add example for GetIsDragRegion
| - **High flexibility** (simple overrides where needed). | ||
| - **Consistent, accessible behavior** aligned with product expectations. | ||
|
|
||
| **XAML sample** |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
| 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)**. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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"> |
There was a problem hiding this comment.
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"?
There was a problem hiding this comment.
But what's draggable is the window, not the element.
There was a problem hiding this comment.
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."
There was a problem hiding this comment.
(Edit: Removed after some reflection.)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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** |
There was a problem hiding this comment.
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 --> |
There was a problem hiding this comment.
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"><TitleBar> | ||
| <TitleBar.Content> | ||
| <TextBlock Text="My App" /> | ||
| <AutoSuggestBox TitleBar.IsDragRegion="True" /> |
There was a problem hiding this comment.
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.
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); |
There was a problem hiding this comment.
SAMPLE: Add example for GetIsDragRegion
| namespace Microsoft.UI.Xaml.Controls | ||
| { | ||
| // Attached property used for per-element overrides | ||
| static DependencyProperty IsDragRegionProperty { get; }; |
There was a problem hiding this comment.
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`: |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
This only lists namespace. This should also show these inside the TitleBar class.


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:
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.IsDragRegionattached 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?
Screenshots (if appropriate):