Это происходит потому, что DataTemplate является «оболочкой» вокруг содержимого кнопки (Button.Content) и использует это содержимое как собственный DataContext.Если Content не указан, DataContext из DataTemplate имеет значение null, и привязка не выполняется.
Для правильной работы кода необходимо указать свойство Button.Content (это должен быть экземпляр класса UserName).
Вы можете использовать DataContext кнопки в качестве содержимого кнопки (этот способ уродлив, как утка).):
<Button Content="{Binding RelativeSource={RelativeSource Self}, Path=DataContext}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid Width="300" Height="150">
<ContentPresenter>
<ContentPresenter.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="50">
<TextBlock Text="Name" />
<TextBox x:Name="userdata" Text="{Binding Name, Mode=TwoWay}" Margin="5" Width="100" />
<Button Content="Show Name"></Button>
</StackPanel>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</Grid>
</ControlTemplate>
</Button.Template>
Когда вы удаляете DataTemplate и ContentPresenter из дерева, тогда TextBox просто наследует DataContext родителя (экземпляр UserName), поэтому привязка работает правильно.
Лучшийпуть идет по шаблону MVVM.
DataContext окна:
public class MainWindowViewModel : INotifyPropertyChanged
{
public UserName User { get; } = new UserName();
}
Назначить контекст данных окна:
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
Привязать кнопку к пользователю:
<Button Content="{Binding User}">
<Button.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="50">
<TextBlock Text="Name" />
<TextBox x:Name="userdata" Text="{Binding Name, Mode=TwoWay}" Margin="5" Width="100" />
<Button Content="Show Name"></Button>
</StackPanel>
</DataTemplate>
</Button.ContentTemplate>
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid Width="300" Height="150">
<ContentPresenter/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>