| MAUI-Application-Tag | MAUI-App-LifeCycle | |
Behaviors in .NET MAUI |
Behaviors allow you to add reusable functionality to UI controls without subclassing them. They are attached to controls and can respond to events or apply logic dynamically.
EventToCommandBehavior.Behavior<T>.
Control (e.g., Entry)
└── Behaviors Collection
└── Behavior
├── OnAttachedTo()
└── OnDetachingFrom()
public class NumericValidationBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry entry)
{
entry.TextChanged += OnEntryTextChanged;
base.OnAttachedTo(entry);
}
protected override void OnDetachingFrom(Entry entry)
{
entry.TextChanged -= OnEntryTextChanged;
base.OnDetachingFrom(entry);
}
void OnEntryTextChanged(object sender, TextChangedEventArgs args)
{
bool isValid = int.TryParse(args.NewTextValue, out _);
((Entry)sender).TextColor = isValid ? Colors.Black : Colors.Red;
}
}
Usage in XAML:
<Entry Placeholder="Enter number">
<Entry.Behaviors>
<local:NumericValidationBehavior />
</Entry.Behaviors>
</Entry>
EventToCommandBehavior binds an event to a command in your ViewModel, enabling MVVM-friendly event handling.
<Entry Placeholder="Type something">
<Entry.Behaviors>
<xct:EventToCommandBehavior
EventName="TextChanged"
Command="{Binding TextChangedCommand}"
CommandParameter="{Binding Source={x:Reference MyEntry}, Path=Text}" />
</Entry.Behaviors>
</Entry>
ViewModel Command:
public ICommand TextChangedCommand => new Command<string>(text =>
{
Console.WriteLine($"Text changed: {text}");
});
OnDetachingFrom() to avoid memory leaks.Behaviors in .NET MAUI allow you to add reusable functionality to UI controls. There are two main types: Normal Behaviors and Attached Behaviors.
Normal behaviors inherit from Behavior<T> and are attached to a control via its Behaviors collection.
<Behaviors> in XAML.Example:
<Entry Placeholder="Enter number">
<Entry.Behaviors>
<local:NumericValidationBehavior />
</Entry.Behaviors>
</Entry>
Attached behaviors use attached properties to apply logic declaratively without adding a Behavior object explicitly.
Example:
<Entry local:AttachedBehavior.IsNumeric="True" />
Attached Behavior Class:
public static class AttachedBehavior
{
public static readonly BindableProperty IsNumericProperty =
BindableProperty.CreateAttached("IsNumeric", typeof(bool), typeof(AttachedBehavior), false, propertyChanged: OnIsNumericChanged);
public static bool GetIsNumeric(BindableObject view) => (bool)view.GetValue(IsNumericProperty);
public static void SetIsNumeric(BindableObject view, bool value) => view.SetValue(IsNumericProperty, value);
private static void OnIsNumericChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is Entry entry && (bool)newValue)
{
entry.TextChanged += (s, e) =>
{
bool isValid = int.TryParse(e.NewTextValue, out _);
entry.TextColor = isValid ? Colors.Black : Colors.Red;
};
}
}
}
| Feature | Normal Behavior | Attached Behavior |
|---|---|---|
| How applied | Inside <Behaviors> collection | Using attached property in XAML |
| Reusability | Good for specific controls | Great for global or declarative usage |
| Complexity | Easier to implement | Requires attached property boilerplate |
Normal Behavior: Control → Behaviors Collection → BehaviorAttached Behavior: Control → Attached Property → Static Class Logic
| MAUI-Application-Tag | MAUI-App-LifeCycle | |