--- name: make-wpf-custom-control description: WPF CustomControl generation wizard. Specify control name and base class to auto-generate C# class and XAML style. disable-model-invocation: true argument-hint: [ControlName] [BaseClass] --- # WPF CustomControl Generation User input: $ARGUMENTS ## Workflow ### Step 1: Parse Arguments Extract control name and base class from `$ARGUMENTS`: - Format: `ControlName BaseClass` (e.g., `MyButton Button`, `CircularProgress Control`) - If base class is omitted, default to `Control` ### Step 2: Validate Input - Control name must be PascalCase - Base class must be valid WPF control (Button, Control, ContentControl, ItemsControl, etc.) ### Step 3: Generate C# Class File Create `[ControlName].cs`: ```csharp using System.Windows; using System.Windows.Controls; namespace [ProjectNamespace].Controls; /// /// [ControlName] - Custom WPF control based on [BaseClass] /// [TemplatePart(Name = "PART_Root", Type = typeof(Border))] [TemplateVisualState(GroupName = "CommonStates", Name = "Normal")] [TemplateVisualState(GroupName = "CommonStates", Name = "MouseOver")] [TemplateVisualState(GroupName = "CommonStates", Name = "Pressed")] [TemplateVisualState(GroupName = "CommonStates", Name = "Disabled")] public class [ControlName] : [BaseClass] { #region Static Constructor static [ControlName]() { DefaultStyleKeyProperty.OverrideMetadata( typeof([ControlName]), new FrameworkPropertyMetadata(typeof([ControlName]))); } #endregion #region Dependency Properties /// /// Example dependency property /// public static readonly DependencyProperty ExampleProperty = DependencyProperty.Register( nameof(Example), typeof(string), typeof([ControlName]), new FrameworkPropertyMetadata( defaultValue: string.Empty, flags: FrameworkPropertyMetadataOptions.AffectsRender, propertyChangedCallback: OnExampleChanged)); public string Example { get => (string)GetValue(ExampleProperty); set => SetValue(ExampleProperty, value); } private static void OnExampleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is [ControlName] control) { control.OnExampleChanged((string)e.OldValue, (string)e.NewValue); } } protected virtual void OnExampleChanged(string oldValue, string newValue) { // Handle property change } #endregion #region Template Parts private Border? _partRoot; public override void OnApplyTemplate() { base.OnApplyTemplate(); _partRoot = GetTemplateChild("PART_Root") as Border; UpdateVisualState(false); } #endregion #region Visual States private void UpdateVisualState(bool useTransitions) { if (!IsEnabled) { VisualStateManager.GoToState(this, "Disabled", useTransitions); } else if (IsMouseOver) { VisualStateManager.GoToState(this, "MouseOver", useTransitions); } else { VisualStateManager.GoToState(this, "Normal", useTransitions); } } protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e) { base.OnMouseEnter(e); UpdateVisualState(true); } protected override void OnMouseLeave(System.Windows.Input.MouseEventArgs e) { base.OnMouseLeave(e); UpdateVisualState(true); } #endregion } ``` ### Step 4: Generate XAML Style File Create `Themes/[ControlName].xaml`: ```xml ``` ### Step 5: Update Generic.xaml Add to `Themes/Generic.xaml` MergedDictionaries: ```xml ``` ## Output Summary After generation, provide: 1. Created files list 2. Next steps for customization 3. Usage example in XAML ```xml ```