协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
desktop-uwp【开发与工程】Use when the user asks about Universal Windows Platform (UWP) development, WinRT APIs, XAML UWP, Windows Store apps, or UWP lifecycle. Do NOT use for: WinUI 3 (desktop-winui3), WPF (desktop-wpf), or WinForms (desktop-winforms).
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Build Universal Windows Platform (UWP) applications — Microsoft's modern Windows app platform with XAML UI, WinRT APIs, adaptive layout, and secure sandboxed deployment via the Microsoft Store. UWP emphasizes responsive design, touch-first interaction, and Windows 10/11 integration.
Exact user phrases: "UWP", "Universal Windows Platform", "WinRT", "Windows Store app", "UWP XAML", "Windows Runtime", "AppContainer", "UWP lifecycle", "adaptive trigger", "VisualStateManager".
UWP application architecture with pages, navigation, data model, adaptive layout, and background tasks.
250 lines.
What kind of UWP app?
├── Standard Windows app → NavigationView + Pages
│ → Frame-based navigation with ShellPage
│ → MVVM with Template 10 or Community Toolkit
├── Media/content app → MediaPlayerElement + in-app toolbar
│ → SystemMediaTransportControls, SMTC integration
│ → Background audio, playlist management
├── IoT/embedded → Headless app with background tasks
│ → Windows IoT Core, GPIO, I2C, SPI
│ → App service for communication
├── Xbox app → Gamepad navigation, 10ft UI
│ → Focus visual, XY focus navigation
│ → High contrast, large target sizes
└── Line-of-business → Forms + data + printing + sharing
→ Content dialog, AppBar, Share contract
→ Enterprise sideloading, AppLocker
Launch → OnLaunched (SplashScreen → MainPage)
↓
Running (active, full interaction)
↓ (user switches away / Windows suspends)
Suspending → OnSuspending (save state, release resources)
↓ (5 second limit, app may be terminated)
Terminated → (if resumed: OnLaunched with PreviousExecutionState)
↓ (user switches back, app not terminated)
Resuming → OnResumed (restore state, refresh network)
<!-- Package.appxmanifest (key settings) -->
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
Identity Name="MyCompany.MyApp" Publisher="CN=MyCompany" Version="1.0.0.0" />
<Properties>
<DisplayName>My App</DisplayName>
<PublisherDisplayName>My Company</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22621.0" />
</Dependencies>
<Capabilities>
<Capability Name="internetClient" />
<DeviceCapability Name="microphone" />
<DeviceCapability Name="webcam" />
</Capabilities>
<!-- ShellPage.xaml - NavigationView layout -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<NavigationView x:Name="NavView"
PaneDisplayMode="LeftCompact"
IsSettingsVisible="True"
ItemInvoked="NavView_ItemInvoked">
<NavigationView.MenuItems>
<NavigationViewItem Icon="Home" Content="Home" Tag="home" />
<NavigationViewItem Icon="Library" Content="Library" Tag="library" />
<NavigationViewItemSeparator />
<NavigationViewItem Icon="Folder" Content="Projects" Tag="projects" />
</NavigationView.MenuItems>
<Frame x:Name="ContentFrame" />
</NavigationView>
</Grid>
</Page>
// ShellPage.xaml.cs - Navigation
private void NavView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
{
if (args.IsSettingsInvoked)
{
ContentFrame.Navigate(typeof(SettingsPage));
return;
}
var tag = (args.InvokedItemContainer as NavigationViewItem)?.Tag?.ToString();
switch (tag)
{
case "home":
ContentFrame.Navigate(typeof(HomePage));
break;
case "library":
ContentFrame.Navigate(typeof(LibraryPage));
break;
case "projects":
ContentFrame.Navigate(typeof(ProjectsPage));
break;
}
}
// ViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
private string title = "My UWP App";
[ObservableProperty]
private Item? selectedItem;
public ObservableCollection<Item> Items { get; } = new();
[RelayCommand]
private async Task LoadItemsAsync()
{
// Simulate async load
await Task.Delay(500);
Items.Clear();
foreach (var item in await _dataService.GetItemsAsync())
{
Items.Add(item);
}
}
[RelayCommand]
private async Task DeleteItemAsync(Item item)
{
Items.Remove(item);
await _dataService.DeleteItemAsync(item.Id);
}
}
<!-- Adaptive page with VisualStateManager -->
<Page>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="WideLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1024" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ItemGrid.Columns" Value="4" />
<Setter Target="DetailPanel.Visibility" Value="Visible" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="MediumLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ItemGrid.Columns" Value="2" />
<Setter Target="DetailPanel.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="NarrowLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ItemGrid.Columns" Value="1" />
<Setter Target="DetailPanel.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition x:Name="DetailPanel" Width="*" />
</Grid.ColumnDefinitions>
<GridView x:Name="ItemGrid" Grid.Column="0">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" />
<TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextBlockStyle}" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<ScrollViewer Grid.Column="1" x:Name="DetailPanel">
<!-- Detail content -->
</ScrollViewer>
</Grid>
</Page>
// WindowsRuntimeComponent/BackgroundTask.cs
public sealed class MyBackgroundTask : IBackgroundTask
{
private BackgroundTaskDeferral? _deferral;
public async void Run(IBackgroundTaskInstance taskInstance)
{
_deferral = taskInstance.GetDeferral();
try
{
// Do background work
var settings = ApplicationData.Current.LocalSettings;
settings.Values["LastRunTime"] = DateTime.Now.ToString();
// Update tile
var updater = TileUpdateManager.CreateTileUpdaterForApplication();
var tileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Text04);
updater.Update(new TileNotification(tileXml));
// Send toast if needed
var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText02);
var toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
finally
{
_deferral?.Complete();
}
}
}
// App.xaml.cs
sealed partial class App : Application
{
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
// Check for previous execution state
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
// Restore saved state
RestoreState();
}
var shell = new ShellPage();
Window.Current.Content = shell;
Window.Current.Activate();
// Register for lifecycle events
Application.Current.Suspending += OnSuspending;
Application.Current.Resuming += OnResuming;
}
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
await SaveStateAsync();
deferral.Complete();
}
private void OnResuming(object sender, object e)
{
RefreshNetworkState();
}
}
// Mica/acrylic backgrounds
using Windows.UI.Composition;
using Windows.UI.ViewManagement;
// Enable Mica (Win11 22000+)
var settings = new UISettings();
var accentColor = settings.GetColorValue(UIColorType.Accent);
// Title bar customization
var titleBar = ApplicationView.GetForCurrentView().TitleBar;
titleBar.ButtonBackgroundColor = Colors.Transparent;
// Snap layout integration
ApplicationView.GetForCurrentView().SetPreferredMinSize(new Size(400, 300));
| Pitfall | Description | Prevention |
|---|---|---|
| App suspension data loss | State not saved before suspend | Save critical state in OnSuspending with deferral |
| .NET Native issues | Missing serialization, reflection | Use DataContractJsonSerializer, avoid late binding |
| Package limitations | File system, registry access restricted | Use ApplicationData, FutureAccessList for known folders |
| x:Bind limitations | Can't bind to methods, indexers, nested properties | Use Binding with converter as fallback |
| UI thread blocking | Async void instead of Task | Always async Task, not async void (except event handlers) |
| No adaptive layout | App looks wrong on different screens | AdaptiveTrigger, VisualStateManager, RelativePanel |
| Missing capability | App crashes when accessing camera, location, etc. | Declare required capabilities in manifest |
| Background task timeout | Tasks killed after 30 seconds | Use deferral, stay under 30s wall-clock time |
| Large package size | Including unnecessary WinMD references | Remove unused SDKs, optimize assets |
| Practice | Rationale |
|---|---|
| Use CommunityToolkit.Mvvm | MVVM source generators, no boilerplate |
| Prefer x:Bind over Binding | Compiled bindings are faster, type-safe |
| Use AdaptiveTrigger for layout | Automatic responsive design without code-behind |
| Store state in OnSuspending | 5-second limit, use deferral for async |
| Use Connected Animation | Native-feeling page transitions |
| Register background tasks with conditions | Battery, internet, user-present to extend lifetime |
| Use DesignTimeData | Better XAML designer experience |
| Version package manifest | Store updates require incrementing version |
| Test with App Analysis Kit | Detect perf issues, missing capabilities |
| Use WinUI 2.x controls | Modern UI over built-in UWP controls |
<Extensions>
<uap:Extension Category="windows.shareTarget">
<uap:ShareTarget Description="Share to My App">
<uap:DataFormat>Text</uap:DataFormat>
<uap:DataFormat>Bitmap</uap:DataFormat>
<uap:DataFormat>StorageItems</uap:DataFormat>
</uap:ShareTarget>
</uap:Extension>
</Extensions>
var builder = new ToastContentBuilder()
.AddText("Hello from UWP!")
.AddButton(new ToastButton()
.SetContent("Reply")
.AddArgument("action", "reply"))
.AddInlineImage(new Uri("ms-appx:///Assets/logo.png"));
builder.Show();
Hand off to desktop-winui3 for WinUI 3 migration. Hand off to design-accessibility for UIA/Narrator testing.
` interface EventObserver { onEvent(event: T): Promise; }
class EventBus { private observers: Set<EventObserver> = new Set(); subscribe(observer: EventObserver): void { this.observers.add(observer); } unsubscribe(observer: EventObserver): void { this.observers.delete(observer); } async emit(event: T): Promise { const results = Array.from(this.observers).map(o => o.onEvent(event)); await Promise.allSettled(results); } } `
config: defaults: timeout: 30s retryCount: 3 overrides: production: timeout: 60s retryCount: 5 development: timeout: 300s retryCount: 1
| Metric | Threshold | Severity | Action |
|---|---|---|---|
| Error rate | > 1% over 5min | Critical | Page on-call |
| p99 latency | > 2s over 5min | Warning | Investigate |
| Throughput drop | > 50% over 1min | Critical | Check upstream |
| Queue depth | > 1000 over 1min | Warning | Scale consumers |
| Disk usage | > 85% | Warning | Clean or expand |
| Memory usage | > 90% heap | Critical | Restart or scale |
| Anti-Pattern | Symptom | Root Cause | Solution |
|---|---|---|---|
| Premature optimization | Complex code for no measured benefit | Guessing instead of profiling | Measure first, optimize based on data |
| Copy-paste reuse | Duplicate code across codebase | Lack of abstraction | Extract shared logic into libraries |
| Gold-plating | Features with no current requirement | Over-engineering | YAGNI — build what's needed now |
| Magical thinking | Assumptions without validation | Skipping error handling | Handle all failure modes explicitly |
Cache hierarchy: L1 (in-memory local) → L2 (distributed Redis/Memcached) → L3 (CDN/Edge). Cache invalidation: TTL-based (simple, stale), event-based (complex, fresh), write-through (consistent, higher write latency), write-behind (fast writes, eventual consistency).
| Decision | UWP | WinUI 3 |
|---|---|---|
| Platform | Windows 10+ Universal | Windows 10+ Desktop |
| Deployment | Store, sideload | MSIX, EXE |
| WinRT access | Full | Partial (limited APIs) |
| .NET version | .NET Native / WinRT | .NET 6+ (desktop) |
| XAML stack | Built-in UWP XAML | WinUI 3 NuGet package |
| Future | Maintenance mode | Active development |
| Best for | Existing UWP apps, Store | New Windows desktop apps |
| Aspect | MVVM | Code-Behind |
|---|---|---|
| Testability | ViewModel is testable | Difficult (UI coupling) |
| Separation | Clear (View/ViewModel/Model) | Mixed |
| Data binding | Full XAML binding | Event handlers |
| Complexity | Higher (bindings, commands) | Lower (direct access) |
| Team scale | Large teams | Small projects, prototypes |