---
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
```