The TextBox control (Microsoft.UI.Xaml.Controls.TextBox
) exposes an "IsReadonly" property, which seems to differ from !IsEnabled in the following ways:
Other textbox-like controls, such as the NumberBox and AutoSuggestBox, have no such property. Is there any way to convince other controls that are visually similar to a TextBox to have ReadOnly behaviour?
AutoSuggestBox and NumberBox have an inner TextBox
. You can access it with the CommunityToolkit.WinUI.Extensions's FindDescendant()
.
For example, you can create an AttachedProperty like this:
public static class Extensions
{
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.RegisterAttached(
"IsReadOnly",
typeof(bool),
typeof(Extensions),
new PropertyMetadata(default, OnIsReadOnlyPropertyChanged));
public static bool GetIsReadOnly(DependencyObject obj) => (bool)obj.GetValue(IsReadOnlyProperty);
public static void SetIsReadOnly(DependencyObject obj, bool value) => obj.SetValue(IsReadOnlyProperty, value);
private static void OnIsReadOnlyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not FrameworkElement element)
{
return;
}
element.Loaded -= Element_Loaded;
if (element.IsLoaded is false)
{
element.Loaded += Element_Loaded;
return;
}
_ = TryUpdateIsReadOnly(element);
}
private static void Element_Loaded(object sender, RoutedEventArgs e)
{
_ = TryUpdateIsReadOnly(sender);
}
private static bool TryUpdateIsReadOnly(object sender)
{
if (sender is not FrameworkElement element ||
element.FindDescendant<TextBox>() is not TextBox innerTextBox)
{
return false;
}
innerTextBox.IsReadOnly = GetIsReadOnly(element);
System.Diagnostics.Debug.WriteLine($"{element.GetType()} IsReadOnly: {innerTextBox.IsReadOnly}");
return true;
}
}
Then use it like this:
<StackPanel Spacing="8">
<ToggleSwitch
x:Name="IsReadOnlyToggleSwitch"
Header="IsReadOnly"
OffContent="False"
OnContent="True" />
<TextBox
IsReadOnly="{x:Bind IsReadOnlyToggleSwitch.IsOn, Mode=OneWay}"
Text="TextBox" />
<AutoSuggestBox
local:Extensions.IsReadOnly="{x:Bind IsReadOnlyToggleSwitch.IsOn, Mode=OneWay}"
Text="AutoSuggestBox" />
<NumberBox
local:Extensions.IsReadOnly="{x:Bind IsReadOnlyToggleSwitch.IsOn, Mode=OneWay}"
Value="12345" />
</StackPanel>