es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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

Tags:  , ,

Answer

  1. Avatar for 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:

    <textbox text="{Binding TextBoxText, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" grid.row="1" grid.column="0" height="20">
        <textbox.style>
            <style targettype="TextBox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsChecked, ElementName=checkBox}" Value="True">
                        <Setter Property="IsEnabled" Value="False"/>
                    </DataTrigger>
                </Style.Triggers>
            </style>
        </textbox.style>
    </textbox>
    
    <checkbox x:name="checkBox" content="Deshabilitado" ischecked="{Binding CheckBoxChecked, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" grid.row="1" grid.column="1" margin="5,5,8,5"></checkbox>
    

    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.

Comments are closed.