Gordon Allocman
Gordon Allocman

Reputation: 778

Switching bindings on a textbox based on radio button selection

The scenario is that I have three radio buttons that each correspond to a different way a function should be evaluated. I have one textbox where the user can enter in a value, and I want the value to persist associated with the radio button that was selected when the value was entered. In the code behind I have three variables (one for each type of value) and the way I am currently maintaining the data is each time the checked or unchecked event gets triggered I am loading the proper value to the textbox and storing the old value in the proper variable. Of note, all three variables are the same type (string).

I know this is not the best way to go about this so I would like to know if there was some way to bind the textbox to all of the variables and have it show the proper value based on which radio button is selected. I have a hunch that it involves using a multibinding with a dataconverter, but I am not sure how to give the data converter state information to decide which value to display or which variable it needs to store the old value to (I could switch to an array but I would still need to be able to get the radiobox selection in the converter). If you could give me some guidance about how to go about doing this that would be great. In case it wasn't clear I am working in C#/Xaml on a WPF application.

Some snippets of what I currently have

Sample Unchecked Event

private void Fixed_Unchecked(object sender, RoutedEventArgs e)
    {
        if (Value != null)
        {
            LastFixedValue = Value.Text;
        }
    }

Sample Checked Event

private void Fixed_Checked(object sender, RoutedEventArgs e)
        {
            if (PercentSign != null)
            {
                PercentSign.Visibility = Visibility.Hidden;
            }
            if (Value != null)
            {
                Value.IsReadOnly = false;
                Value.Text = LastFixedValue;
                Value.Background = Brushes.White;
            }
        }

I would still need some of the checked/unchecked events to handle the ui changes, but I would like to reduce the amount of code and handle binding properly

Upvotes: 2

Views: 1796

Answers (1)

Rachel
Rachel

Reputation: 132548

If I am understanding your requirements correctly, here is what my solution would be :

public class MyViewModel : INotifyPropertyChanged
{
    public Dictionary<string, string> AvailableItems { get; set; }

    private string _selectedItem;
    public string SelectedItem 
    {
        get { return _selectedItem; }
        set 
        {
            _selectedItem = value;
            RaisePropertyChanged("SomeValue");
            RaisePropertyChanged("Value"); // Notify Value it has changed too
        }
    }

    public string Value
    {
        get { return AvailableItems[SelectedItem]; }
        set { AvailableItems[SelectedItem] = value; }
    }

    public MyViewModel()
    {
        AvailableItems = new Dictionary<string, string>();
        AvailableItems.Add("Fixed", string.Empty);
        AvailableItems.Add("Percent", string.Empty);
        AvailableItems.Add("Variable", string.Empty);

        SelectedItem = AvailableItems[0];
    }
}

XAML

<ListBox ItemsSource="{Binding AvailableItems}"
         DisplayMemberPath="Key"
         SelectedValuePath="Key"
         SelectedValue="{Binding SelectedItem}"
         Style="{StaticResource RadioButtonListBoxStyle}" />

<TextBox Text="{Binding Value}" />

Note that I'm using a ListBox for this instead of defining each RadioButton individually... this is common for when I want to display a list of items where the user can only select one item. Its much easier than maintaining X number of boolean properties and tracking each Checked value.

The RadioButtonListBoxStyle usually just overwrites the default template to draw each ListBoxItem using a RadioButton, like this :

<Style x:Key="RadioButtonListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="Margin" Value="2, 2, 2, 0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <RadioButton
                                    Content="{TemplateBinding ContentPresenter.Content}" VerticalAlignment="Center"
                                    IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>

                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

This will maintain each text value in a Dictionary, with the key for each item being the associated RadioButton text. It is also very easy to expand upon or change if needed.

Upvotes: 1

Related Questions