0
votes

I think this is a beginner's question for intermediate stuff in WFP. I have a user control which acts as a radiobutton using two normal buttons: (buttons changes color to show the current choice)

<UserControl x:Class="UI.UserControls.RadioUC" Loaded="UserControl_Loaded">
<Stackpanel DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">

    <TextBlock Text="{Binding Path=Title}"/>

    <Button x:Name="BtnYes" Content="YES" Click="BtnYes_Click">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <i:InvokeCommandAction Command="{Binding Command}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>

        <Button x:Name="BtnNo" Content="NO" Click="BtnNo_Click">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <i:InvokeCommandAction Command="{Binding Command}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
</Stackpanel>
</UserControl>

And the codebehind consists of 2 dependency properties Title & IsYes. When the buttons are clicked using the click events, IsYes property is modified.

public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(RadioUC),
        new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

public static readonly DependencyProperty IsYesProperty = DependencyProperty.Register("IsYes", typeof(bool), typeof(RadioUC),
        new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

public bool IsYes {
        get { return (bool)GetValue(IsYesProperty); }
        set { SetValue(IsYesProperty, value); }
    }

public String Title {
        get { return (String)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

private void BtnYes_Click(object sender, RoutedEventArgs e)
    {
        IsYes = true;
        //BtnYes.Background = new SolidColorBrush(Colors.ForestGreen);
        //BtnNo.Background = new SolidColorBrush(Colors.Gray);
    }

private void BtnNo_Click(object sender, RoutedEventArgs e)
    {
        IsYes = false;
        //BtnNo.Background = new SolidColorBrush(Colors.ForestGreen);
        //BtnYes.Background = new SolidColorBrush(Colors.Gray);
    }

And finally this how I use it:

<uc:RadioUC Title="Is it YES" IsYes="{Binding IsLocalYes, Mode=TwoWay}"/>

When the buttons are clicked individually, the IsYes property of the usercontrol gets modified successfully. There is no problem. The problem is when I modified IsLocalYes programmatically in the hosting window of the usercontrol, this change does not propagate into the usercontrol. So the question is how can I modify IsYes property of the usercontrol when IsLocalYes property changes?

1
What and where is IsLocalYes? - Andy
Have you tried to change the ControlTemplate of RadioButton instead of creating a UserControl? See also docs.microsoft.com/en-us/dotnet/framework/wpf/controls/… - nosale
@Andy, IsLocalYes is a property of the host window's viewmodel where there are many reusable usercontrols. - Doğaç Özen
Three things: First, is the binding actually resolved successfully? In other words, is the DataContext used by the uc:RadioUC actually the viewmodel containing the IsLocalYes property? We can't tell because we cannot see... Second, what does the implementation of the IsLocalYes property look like? Third, your dependency property needs to implement a callbakc that manipulates the user control whenever its value changes from the "outside". - user2819245
@elgonzo, I cannot figure out how to implement a callback. The first two point are okay. I will edit the question right away. Can you tell me how to put a callback in the usercontrol? - Doğaç Özen

1 Answers

0
votes

Instead of creating your own UserControl, for what you want to achieve it's better to use a ToggleButton and change the ControlTemplate/Style.

Read also this article


Solution:

ToggleButton-Style:

<Style x:Key="YesNoToggleButtonStyle" TargetType="ToggleButton" BasedOn="{StaticResource {x:Type ToggleButton}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Grid x:Name="templateRoot" Background="Transparent" SnapsToDevicePixels="True">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    <StackPanel Grid.Column="1" Orientation="Horizontal">
                        <Grid x:Name="PART_GRIDYES" Background="Gray" MinWidth="6" MinHeight="6">
                            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">YES</TextBlock>
                        </Grid>
                        <Grid x:Name="PART_GRIDNO" Background="Gray" MinWidth="6" MinHeight="6">
                            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">NO</TextBlock>
                        </Grid>
                    </StackPanel>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="true">
                        <Setter TargetName="PART_GRIDYES" Property="Background" Value="ForestGreen"></Setter>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="false">
                        <Setter TargetName="PART_GRIDNO" Property="Background" Value="ForestGreen"></Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Use it like this:

<ToggleButton Style="{StaticResource YesNoToggleButtonStyle}" IsChecked="{Binding IsLocalYes, Mode=TwoWay}">Is it YES</ToggleButton>