Я думаю, что ваше лучшее решение здесь - это использовать вложенные свойства вместо подклассов. Это позволит вам съесть свой торт и съесть его тоже.
Вместо написания этого:
<my:CustomButton ImageSource="Abc" Text="Def" ... />
Вы бы написали это:
<Button my:ButtonLook.ImageSource="Abc" my:ButtonLook.Text="Def" ... />
Это будет работать с привязкой данных и всем прочим. Чтобы реализовать это, создайте класс «ButtonLook», производный от DependencyObject, и создайте два прикрепленных свойства, используя фрагмент «propa» в Visual Studio. Затем установите PropertyChangedCallback для каждого из них, чтобы создать обновление свойства ContentControl.Content для всех объектов, к которым они присоединены.
Альтернативное решение - встроить скрытый RadioButton в ваш подкласс CustomRadioButton, дать ему пустой шаблон, чтобы сделать его невидимым, и связать свойства IsChecked и GroupName:
<ControlTemplate TargetType="my:CustomRadioButton">
<Grid>
<RadioButton IsChecked="{Binding ToggleButton.IsChecked, RelativeSource={RelativeSource TemplatedParent}}"
GroupName="{TemplateBinding GroupName}">
<RadioButton.Template><ControlTemplate /></RadioButton.Template>
</RadioButton>
... visual part here ...
Убедитесь, что ваши подклассы CustomToggleButton и CustomRadioButton используют AddOwner для создания свойств DependencyProperties, таких как IsChecked и GroupName, а не для создания новых.