Cursor rule
.cursor/rules/wpf-ui-patterns.mdcWPF-specific UI patterns and best practices
Cursor rules
Quality
66/100
Scores the file, not the repository.Length
793 words
40 headings · 28 code blocksRepository
103
— · pushed 17 days agoLast changed
3 days ago
First indexed 3 days ago.1234567# WPF UI Patterns89## Window Lifecycle1011### Window Creation Pattern12Windows are typically created once and shown/hidden as needed:1314```csharp15private ChatBoxWindow? _chatBoxWindow;1617public void ShowChatBox()18{19 if (_chatBoxWindow == null)20 {21 _chatBoxWindow = new ChatBoxWindow();22 _chatBoxWindow.Closed += (s, e) => { _chatBoxWindow = null; };23 }2425 _chatBoxWindow.Show();26 _chatBoxWindow.Activate();27}2829public void HideChatBox()30{31 _chatBoxWindow?.Hide();32}33```3435### Window Cleanup36```csharp37protected override void OnClosed(EventArgs e)38{39 // Save window position40 ConfigManager.Instance.SetWindowPosition(41 "ChatBox", Left, Top, Width, Height);4243 // Cleanup resources44 base.OnClosed(e);45}46```4748## XAML Structure4950### Standard Window Attributes51```xml52<Window x:Class="UGTLive.ChatBoxWindow"53 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"54 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"55 Title="ChatBox"56 WindowStyle="None"57 AllowsTransparency="True"58 Background="Transparent"59 ResizeMode="CanResize"60 Topmost="{Binding IsAlwaysOnTop}"61 ShowInTaskbar="False">62</Window>63```6465### Resource Dictionaries66Define styles in ResourceDictionary:6768```xml69<Window.Resources>70 <Style x:Key="ModernButton" TargetType="Button">71 <Setter Property="Background" Value="#FF2D2D30"/>72 <Setter Property="Foreground" Value="White"/>73 <Setter Property="BorderThickness" Value="0"/>74 <Setter Property="Padding" Value="10,5"/>75 </Style>76</Window.Resources>77```7879## Data Binding8081### Two-Way Binding Pattern82```xml83<TextBox Text="{Binding ApiKey, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>84<CheckBox IsChecked="{Binding IsEnabled, Mode=TwoWay}"/>85<ComboBox SelectedItem="{Binding SelectedModel, Mode=TwoWay}"/>86```8788### Code-Behind Binding89```csharp90// Set DataContext91this.DataContext = this;9293// Implement INotifyPropertyChanged94public event PropertyChangedEventHandler? PropertyChanged;9596private string _apiKey = "";97public string ApiKey98{99 get => _apiKey;100 set101 {102 _apiKey = value;103 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ApiKey)));104 }105}106```107108## Event Handlers109110### Standard Event Pattern111```csharp112private void Button_Click(object sender, RoutedEventArgs e)113{114 if (sender is Button button)115 {116 // Handle click117 }118}119120private void TextBox_TextChanged(object sender, TextChangedEventArgs e)121{122 if (sender is TextBox textBox)123 {124 // Handle text change125 }126}127```128129## Window Positioning130131### Load Saved Position132```csharp133private void Window_Loaded(object sender, RoutedEventArgs e)134{135 var pos = ConfigManager.Instance.GetWindowPosition("ChatBox");136 if (pos != null)137 {138 this.Left = pos.X;139 this.Top = pos.Y;140 this.Width = pos.Width;141 this.Height = pos.Height;142 }143 else144 {145 // Center on screen146 this.WindowStartupLocation = WindowStartupLocation.CenterScreen;147 }148}149```150151### Save Position on Move152```csharp153private void Window_LocationChanged(object sender, EventArgs e)154{155 ConfigManager.Instance.SetWindowPosition(156 "ChatBox", Left, Top, Width, Height);157}158```159160## Custom Controls161162### Draggable Window163```csharp164private void Window_MouseDown(object sender, MouseButtonEventArgs e)165{166 if (e.ChangedButton == MouseButton.Left)167 {168 this.DragMove();169 }170}171```172173### Resizable Thumb174```xml175<Thumb DragDelta="Thumb_DragDelta"176 Width="10" Height="10"177 Cursor="SizeNWSE"178 HorizontalAlignment="Right"179 VerticalAlignment="Bottom"/>180```181182```csharp183private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)184{185 this.Width = Math.Max(100, this.Width + e.HorizontalChange);186 this.Height = Math.Max(100, this.Height + e.VerticalChange);187}188```189190## Transparent Windows191192### Transparency Setup193```xml194<Window WindowStyle="None"195 AllowsTransparency="True"196 Background="Transparent">197 <Border Background="{Binding BackgroundColor}"198 Opacity="{Binding Opacity}"199 CornerRadius="5">200 <!-- Content -->201 </Border>202</Window>203```204205### Opacity Binding206```csharp207public double Opacity208{209 get => _opacity;210 set211 {212 _opacity = value;213 this.Opacity = value / 100.0; // Convert 0-100 to 0-1214 }215}216```217218## Always-On-Top219220### Topmost Property221```xml222<Window Topmost="{Binding IsAlwaysOnTop}"/>223```224225```csharp226public bool IsAlwaysOnTop227{228 get => this.Topmost;229 set => this.Topmost = value;230}231```232233## Text Display234235### TextBlock with Formatting236```xml237<TextBlock TextWrapping="Wrap">238 <Run Text="{Binding SourceText}" Foreground="Gray"/>239 <LineBreak/>240 <Run Text="{Binding TranslatedText}" Foreground="White" FontWeight="Bold"/>241</TextBlock>242```243244### ScrollViewer Pattern245```xml246<ScrollViewer VerticalScrollBarVisibility="Auto"247 HorizontalScrollBarVisibility="Disabled">248 <StackPanel Name="ContentPanel">249 <!-- Dynamic content -->250 </StackPanel>251</ScrollViewer>252```253254### Auto-Scroll to Bottom255```csharp256private void ScrollToBottom()257{258 Application.Current.Dispatcher.Invoke(() =>259 {260 if (ScrollViewer != null)261 {262 ScrollViewer.ScrollToEnd();263 }264 });265}266```267268## Color Pickers269270### Color Dialog Pattern271```csharp272using System.Windows.Forms;273274private void PickColorButton_Click(object sender, RoutedEventArgs e)275{276 using var colorDialog = new ColorDialog();277 colorDialog.Color = System.Drawing.Color.FromArgb(278 (int)((Color)BackgroundColor).A,279 (int)((Color)BackgroundColor).R,280 (int)((Color)BackgroundColor).G,281 (int)((Color)BackgroundColor).B);282283 if (colorDialog.ShowDialog() == DialogResult.OK)284 {285 var wpfColor = Color.FromArgb(286 colorDialog.Color.A,287 colorDialog.Color.R,288 colorDialog.Color.G,289 colorDialog.Color.B);290 BackgroundColor = wpfColor;291 }292}293```294295## Animations296297### Fade Animation298```xml299<Window.Resources>300 <Storyboard x:Key="FadeIn">301 <DoubleAnimation Storyboard.TargetProperty="Opacity"302 From="0" To="1" Duration="0:0:0.3"/>303 </Storyboard>304</Window.Resources>305```306307```csharp308private void FadeIn()309{310 var storyboard = (Storyboard)FindResource("FadeIn");311 storyboard?.Begin(this);312}313```314315## ComboBox Binding316317### ComboBox with Items318```xml319<ComboBox Name="ModelComboBox"320 SelectedItem="{Binding SelectedModel, Mode=TwoWay}">321 <ComboBoxItem Content="gemini-1.5-flash"/>322 <ComboBoxItem Content="gemini-1.5-pro"/>323 <ComboBoxItem Content="gemini-2.0-flash"/>324</ComboBox>325```326327```csharp328private void LoadModels()329{330 ModelComboBox.Items.Clear();331 var models = new[] { "gemini-1.5-flash", "gemini-1.5-pro", "gemini-2.0-flash" };332 foreach (var model in models)333 {334 ModelComboBox.Items.Add(model);335 }336337 // Set selected item338 var savedModel = ConfigManager.Instance.GetGeminiModel();339 ModelComboBox.SelectedItem = savedModel;340}341```342343## Tab Control Pattern344345### Settings Window Tabs346```xml347<TabControl>348 <TabItem Header="General">349 <!-- General settings -->350 </TabItem>351 <TabItem Header="OCR">352 <!-- OCR settings -->353 </TabItem>354 <TabItem Header="Translation">355 <!-- Translation settings -->356 </TabItem>357</TabControl>358```359360## Status Bar Updates361362### Status Message Pattern363```csharp364public void UpdateStatus(string message, StatusType type = StatusType.Info)365{366 Application.Current.Dispatcher.Invoke(() =>367 {368 StatusText.Text = message;369 StatusText.Foreground = type switch370 {371 StatusType.Error => Brushes.Red,372 StatusType.Warning => Brushes.Orange,373 _ => Brushes.White374 };375376 // Auto-fade after 3 seconds377 _statusTimer?.Stop();378 _statusTimer = new DispatcherTimer379 {380 Interval = TimeSpan.FromSeconds(3)381 };382 _statusTimer.Tick += (s, e) =>383 {384 StatusText.Text = "";385 _statusTimer.Stop();386 };387 _statusTimer.Start();388 });389}390```391392## Dialog Windows393394### Modal Dialog Pattern395```csharp396var dialog = new SettingsWindow();397dialog.Owner = this;398dialog.ShowDialog(); // Blocks until closed399```400401### Confirmation Dialog402```csharp403var result = MessageBox.Show(404 "Are you sure you want to delete this?",405 "Confirm",406 MessageBoxButton.YesNo,407 MessageBoxImage.Question);408409if (result == MessageBoxResult.Yes)410{411 // Perform action412}413```414
Also in SethRobinson/UGTLive
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| SethRobinson/UGTLive.cursor/rules/ui-ux-patterns.mdc · 103 | Cursor rules | stylearchtypesui+1 | 62/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/architecture-patterns.mdc · 103 | Cursor rules | buildtestlint-formatstyle+6 | 77/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/async-threading-patterns.mdc · 103 | Cursor rules | styleuido-not | 65/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/code-style-conventions.mdc · 103 | Cursor rules | stylearchtypesdocs | 62/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/configuration-management.mdc · 103 | Cursor rules | archsecuritydatabaseapi+1 | 65/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/debugging-testing.mdc · 103 | Cursor rules | buildteststylearch+3 | 69/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/locale-invariant-formatting.mdc · 103 | Cursor rules | lint-formatuido-not | 61/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/service-integration-patterns.mdc · 103 | Cursor rules | buildteststylearch | 69/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/translation-workflow.mdc · 103 | Cursor rules | testlint-formatarchapi+3 | 66/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/ugtlive-project-guide.mdc · 103 | Cursor rules | stylearchuideployment+1 | 69/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/versioning-workflow.mdc · 103 | Cursor rules | stylegitdeploymentagent-behaviour+1 | 62/100 | 3 days ago | |
| SethRobinson/UGTLiveAGENTS.md · 103 | AGENTS.md | testgitsecurityperformance+1 | 74/100 | 3 days ago |
Diff against .cursor/rules/ui-ux-patterns.mdc Diff against .cursor/rules/architecture-patterns.mdc Diff against .cursor/rules/async-threading-patterns.mdc Diff against .cursor/rules/code-style-conventions.mdc Diff against .cursor/rules/configuration-management.mdc Diff against .cursor/rules/debugging-testing.mdc Diff against .cursor/rules/locale-invariant-formatting.mdc Diff against .cursor/rules/service-integration-patterns.mdc Diff against .cursor/rules/translation-workflow.mdc Diff against .cursor/rules/ugtlive-project-guide.mdc Diff against .cursor/rules/versioning-workflow.mdc Diff against AGENTS.md
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| ThanhTrunggDEV/DontBeLazy.cursor/rules/rust-testing.mdc · 6 | Cursor rules | teststyletesting-strategy | 90/100 | 3 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/dart-testing.mdc · 6 | Cursor rules | teststyletypestesting-strategy | 85/100 | 3 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/dart-coding-style.mdc · 6 | Cursor rules | lint-formatstyletypesdo-not | 84/100 | 3 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/rust-security.mdc · 6 | Cursor rules | stylesecuritydatabasedo-not | 80/100 | 3 days ago | |
| imazen/imageflow.cursor/rules/ci.mdc · 4.4k | Cursor rules | setupbuildtestarch+3 | 79/100 | 3 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/rust-coding-style.mdc · 6 | Cursor rules | lint-formatstyle | 78/100 | 3 days ago | |
| ThanhTrunggDEV/DontBeLazy.cursor/rules/dart-hooks.mdc · 6 | Cursor rules | lint-formatarchtesting-strategygit+1 | 78/100 | 3 days ago | |
| SethRobinson/UGTLive.cursor/rules/architecture-patterns.mdc · 103 | Cursor rules | buildtestlint-formatstyle+6 | 77/100 | 3 days ago |
