Существует несколько способов достижения этого с различной степенью простоты повторного использования. У вас может быть DataTemplateSelector, который может вернуть соответствующий DataTemplate для данного свойства (в зависимости от того, как это написано, вы можете использовать его для каждого из ваших свойств).
Вы можете создать DataTemplate для каждого свойства и изменить видимость на основе DataTrigger (это очень раздражает, так как много копирует и вставляет).
Я думаю, что самый простой способ сделать это с помощью специального ControlTemplate для TextBox. По сути, когда он отключен, вместо того, чтобы скрыть его, вы можете просто сделать его похожим на TextBlock:
<ControlTemplate x:Key="PermissionedTextBox" TargetType="{x:Type TextBox}">
<Border x:Name="bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="bd" Property="BorderBrush" Value="{x:Null}" />
<Setter TargetName="bd" Property="Background" Value="{x:Null}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Тогда вы можете использовать его так:
<TextBox Text="{Binding PermissionedText}" IsEnabled="{Binding CanEdit}" />