Search code examples
wpfmvvmtextboxcustom-controlstogglebutton

WPF MVVM - How to Bind Custom Control->ToggleButton.IsChecked to View->TextBox.Text


I am moving over from WinForms to WPF and trying to implement the MVVM pattern for a touchscreen application. I created several custom controls inside a WPF Control Library (dll), and I can bring these controls into the View with no issue. However, I am getting stuck on a purely academic scenario where I want a TextBox inside the View to display my custom control's ToggleButton.IsChecked property as "Checked" and "Unchecked" respectively.

To sum up, I need to know the proper way to expose properties of a control that is inside a custom user control. Then when the exposed property changes update some other control with custom data based on the property that changed.


Solution

  • To sum up, I need to know the proper way to expose properties of a control that is inside a custom user control. Then when the exposed property changes update some other control with custom data based on the property that changed.

    You're describing dependency properties. You need to add a dependency property to your custom control, which you then bind to from inside the control, and from outside it (in your view).

    The first part will depend on whether you're using a UserControl or a Control. Let's say it is a Control, then you would use a TemplatedParent binding in your ControlTemplate:

    <ToggleButton IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent},Path=IsToggleChecked,Mode=TwoWay}" ... />
    

    If on the other hand it is a UserControl, then the approach is similar, but you need to make sure the data context is right. One approach would be to use a FindAncestor binding:

    <ToggleButton IsChecked="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=IsToggleChecked,Mode=TwoWay}" ... />
    

    Now, to add the dependency property, try the Visual Studio code snippet "propdp". It should look something like this:

    public bool IsToggleChecked
    {
        get { return (bool)GetValue(IsToggleCheckedProperty); }
        set { SetValue(IsToggleCheckedProperty, value); }
    }
    public static readonly DependencyProperty IsToggleCheckedProperty =
        DependencyProperty.Register("IsToggleChecked", typeof(bool), typeof(MyCustomControl), new PropertyMetadata(false));
    

    And now finally you can bind your TextBox to the new dependency property:

    <TextBox Text="{Binding ElementName=myCustomControl,Path=IsToggleChecked,Converter={StaticResource BoolToTextConverter}}" />
    <local:MyCustomControl x:Name="myCustomControl" ... />
    

    I assumed that you would want to make an IValueConverter "BoolToTextConverter" that converts the boolean value to the string "Checked" or "Unchecked".