¿Cómo puedo hacer que un usercontrol actualice su propia propiedad?
Tengo un usercontrol en mi aplicación WPF que básicamente es una casilla de verificación con un cuadro de texto. Quiero que el cuadro de texto esté deshabilitado o habilitado en función del estado de la casilla de verificación y que el estado sea enlazable a datos.
Este es mi usercontrol:
XAML
<usercontrol x:class="WpfApp.Views.Elements.TextCheckBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:ignorable="d" d:designheight="450" d:designwidth="800">
<grid>
<grid.rowdefinitions>
<rowdefinition height="*"></rowdefinition>
<rowdefinition height="*"></rowdefinition>
</grid.rowdefinitions>
<grid.columndefinitions>
<columndefinition width="*"></columndefinition>
<columndefinition width="Auto"></columndefinition>
</grid.columndefinitions>
<checkbox content="Disabled" ischecked="{Binding CheckBoxChecked,
Mode=OneWayToSource,
UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" horizontalalignment="Center" verticalalignment="Center" grid.row="1" grid.column="1" margin="5,5,8,5"></checkbox>
<textbox text="{Binding TextBoxText,
Mode=OneWayToSource,
UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" isenabled="{Binding TextBoxEnabled,
Mode=OneWay,
RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" grid.row="1" grid.column="0" height="20"></textbox>
</grid>
</usercontrol>
Codebehind
using System.Windows;
using System.Windows.Controls;
namespace WpfApp.Views.Elements
{
/// <summary>
/// Interaction logic for TextCheckBox.xaml
/// </summary>
public partial class TextCheckBox : UserControl
{
public bool TextBoxEnabled => !CheckBoxChecked;
public string TextBoxText
{
get => (string)GetValue(TextBoxTextProperty);
set => SetValue(TextBoxTextProperty, value);
}
public bool CheckBoxChecked
{
get => (bool)GetValue(CheckBoxCheckedProperty);
set => SetValue(CheckBoxCheckedProperty, value);
}
public event DependencyPropertyChangedEventHandler TextPropertyChanged;
public static readonly DependencyProperty TextBoxTextProperty =
DependencyProperty.Register(nameof(TextBoxText), typeof(string), typeof(TextCheckBox), new PropertyMetadata(OnAnyPropertyChanged));
public static readonly DependencyProperty CheckBoxCheckedProperty =
DependencyProperty.Register(nameof(CheckBoxChecked), typeof(bool), typeof(CheckBoxInput), new PropertyMetadata(OnAnyPropertyChanged));
public TextCheckBox()
=> InitializeComponent();
static void OnAnyPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
=> (obj as TextCheckBox).OnAnyPropertyChanged(args);
void OnAnyPropertyChanged(DependencyPropertyChangedEventArgs args)
=> TextPropertyChanged?.Invoke(this, args);
}
}
No tengo idea de cómo decirle a TextCheckBox que actualice su propiedad “IsEnabled” cuando se marca la casilla de verificación.
Este es el XAML donde estoy usando TextCheckBox y los enlaces están funcionando correctamente:
<usercontrol x:class="WpfApp.Views.MyView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:other="clr-namespace:WpfApp.Other" xmlns:elements="clr-namespace:WpfApp.Views.Elements" mc:ignorable="d" other:viewmodellocator.autowireviewmodel="True" d:designheight="450" d:designwidth="800">
<grid>
<elements:textcheckbox checkboxchecked="{Binding IsChecked,
Mode=OneWayToSource}" textboxtext="{Binding TextContent,
Mode=OneWayToSource,
UpdateSourceTrigger=PropertyChanged}"></elements:textcheckbox>
</grid>
</usercontrol>
EDICIÓN:
Como sugirió Khiro, intenté usar una propiedad de dependencia cuyo valor se establece en el setter de “CheckBoxChecked”.
El codebehind después del cambio quedó así (código modificado con comentarios “Change here” en la línea anterior):
using System.Windows;
using System.Windows.Controls;
namespace WpfApp.Views.Elements
{
/// <summary>
/// Interaction logic for TextCheckBox.xaml
/// </summary>
public partial class TextCheckBox : UserControl
{
// Change here.
public bool TextBoxEnabled => (bool)GetValue(TextBoxEnabledProperty);
public string TextBoxText
{
get => (string)GetValue(TextBoxTextProperty);
set => SetValue(TextBoxTextProperty, value);
}
public bool CheckBoxChecked
{
get => (bool)GetValue(CheckBoxCheckedProperty);
set
{
SetValue(CheckBoxCheckedProperty, value);
// Change here.
SetValue(TextBoxEnabledProperty, !value);
}
}
public event DependencyPropertyChangedEventHandler TextPropertyChanged;
// Change here.
public static readonly DependencyProperty TextBoxEnabledProperty =
DependencyProperty.Register(nameof(TextBoxEnabled), typeof(bool), typeof(CheckBoxInput), new PropertyMetadata(OnAnyPropertyChanged));
public static readonly DependencyProperty TextBoxTextProperty =
DependencyProperty.Register(nameof(TextBoxText), typeof(string), typeof(TextCheckBox), new PropertyMetadata(OnAnyPropertyChanged));
public static readonly DependencyProperty CheckBoxCheckedProperty =
DependencyProperty.Register(nameof(CheckBoxChecked), typeof(bool), typeof(CheckBoxInput), new PropertyMetadata(OnAnyPropertyChanged));
public TextCheckBox()
=> InitializeComponent();
static void OnAnyPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
=> (obj as TextCheckBox).OnAnyPropertyChanged(args);
void OnAnyPropertyChanged(DependencyPropertyChangedEventArgs args)
=> TextPropertyChanged?.Invoke(this, args);
}
}
Pero nada cambió. Hacer clic en la casilla de verificación no deshabilita el TextBox. Además, los puntos de interrupción no están activos en el setter de “CheckBoxChecked”.
Luego intenté la respuesta proporcionada por Clemens y el XAML de mi usercontrol quedó así (solo se publica la parte modificada):
“`
<textbox.style>
</textbox.style>
davy.ai
Una forma de desactivar o activar el cuadro de texto en función del estado del cuadro de selección es mediante el uso de un DataTrigger en el estilo del cuadro de texto.
Aquí hay un ejemplo:
En el ejemplo anterior, el DataTrigger se establece en la propiedad IsChecked del cuadro de selección con el nombre “checkBox”. Cuando se marca la casilla, la propiedad TextBox.IsEnabled se establecerá en falso. Cuando se desmarca, la propiedad TextBox.IsEnabled vuelve a su valor predeterminado, que es verdadero.
Este enfoque no requiere cambios en el código de fondo.