wpfmvvmdata-bindingstylingcontroltemplate

Editing the property of an element within the ControlTemplate in WPF


I have some radio buttons that I'm building a custom control template for. Image of the buttons:
enter image description here

In the control template, each radio button will have a textblock with its name and another textblock below it to indicate if it's unavailable. I want the "Unavailable" text to be visible ONLY when the button is NOT enabled. When the radio button is ENABLED, the "Unavailable" textblock should be collapsed.

Here is the simplified view.xaml for the buttons:


            <RadioButton Name="one"
                         IsEnabled="{Binding One_isAvailable}"
                         Style="{StaticResource RadioButtonTheme}" />
            <RadioButton Name="two"
                         IsEnabled="{Binding Two_isAvailable}"
                         Style="{StaticResource RadioButtonTheme}" />
            <RadioButton Name="three"
                         IsEnabled="{Binding Three_isAvailable}"
                         Style="{StaticResource RadioButtonTheme}"/>

Here is the simplified version of the styling I have so far (RadioButtonTheme.xaml):

<ResourceDictionary>
    <Style BasedOn="{StaticResource {x:Type ToggleButton}}"
           TargetType="{x:Type RadioButton}"
           x:Key="RadioButtonTheme">

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Border CornerRadius="7">

                        <StackPanel VerticalAlignment="Center">
                            <TextBlock HorizontalAlignment="Center"
                                       Text="{TemplateBinding Property=Name}"
                                       Foreground="{TemplateBinding Property=Foreground}">
                            </TextBlock>
                            <TextBlock Name="UnavailableTextBlock"
                                       HorizontalAlignment="Center"
                                       Text="Unavailable"
                                       FontSize="14"
                                       FontStyle="Italic"
                                       Foreground="{TemplateBinding Property=Foreground}">
                            </TextBlock>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

So I've tried setting a couple things:

  1. I set a visiblitity property on the radio button on the view.xaml. I then binded that visibility to the "UnavailableTextBlock" in the radiobuttontheme.xaml and set the rest of the template visiblity to "Visible." I thought that I can leave the template visible except for one element of it. I now don't think that's possible.

  2. I tried directly binding the "UnavailableTextBlock" to the IsEnabled property of the radiobutton, and ran it through a BoolToVisiblityConverter.

<TextBlock Name="UnavailableTextBlock"
           Visibility="{TemplateBinding Property=IsEnabled, Converter={StaticResource BoolToVisConverter}}">

However, I can't seem to get my converter to work inside of the ResourceDictionary. The program will crash with the error: "Cannot find resource named 'BoolToVisConverter'. Resource names are case sensitive"

I have this converter working across my other xaml files since I added it to my <Application.Resources> in the app.xaml. Do I need to link my Resource dictionary to the converter? How do I do that? <ResourceDictionary.Resources> didn't seem to work for me.

  1. I tried adding a datatrigger to the "UnavailableTextBlock" as below:

<TextBlock Name="UnavailableTextBlock"....>
   <TextBlock.Style>
      <Style TargetType="TextBlock">
         <Setter Property="Visibility" Value="Collapsed"/>
            <Style.Triggers>
               <DataTrigger Binding="{TemplateBinding Property=IsEnabled}" Value="false">
                  <Setter Property="Visibility" Value="Visible"/>
                </DataTrigger>
             </Style.Triggers>
       </Style>
    </TextBlock.Style>
</TextBlock>

However, I get an error saying: '"IsEnabled" member is not valid because it does not have a qualifying type name.' I'm guessing that it's referencing the IsEnabled property of the TextBlock and not of the radio button? Although I'm not too sure. I'm still learning WPF.

Thanks for all your help in advance!


Solution

  • If I understand correctly what you want to implement, then you need to use the control template trigger.

        <Style BasedOn="{StaticResource {x:Type ToggleButton}}"
                TargetType="{x:Type RadioButton}"
                x:Key="RadioButtonTheme">
    
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="RadioButton">
                        <Border CornerRadius="7">
                            <StackPanel VerticalAlignment="Center">
                                <TextBlock HorizontalAlignment="Center"
                                        Text="{TemplateBinding Property=Name}"
                                        Foreground="{TemplateBinding Property=Foreground}">
                                </TextBlock>
                                <TextBlock Name="UnavailableTextBlock"
                                        HorizontalAlignment="Center"
                                        Text="Unavailable"
                                        FontSize="14"
                                        FontStyle="Italic"
                                        Foreground="{TemplateBinding Property=Foreground}">
                                </TextBlock>
                            </StackPanel>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="True">
                                <Setter TargetName="UnavailableTextBlock" Property="Visibility" Value="Hidden"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>