custom controles control c# wpf xaml user-controls

c# - controles - WPF UserControl no hereda el DataContext padre



custom control wpf (1)

Intento desarrollar un UserControl reutilizable pero tengo problemas con el enlace. Creé una aplicación más pequeña para probarla pero no pude resolverla, o al menos comprender por qué no funciona como esperaba.

El código está abajo. Lo que esperaría es la instancia de TestUserControl que puse en MainWindow.xaml heredaría el DataContext justo como lo hace el TextBlock. En cambio, DataContext parece ser nulo. ¿Hay alguna razón por la cual el DataContext no se pase? ¿Tengo que configurarlo automáticamente?

MainWindow.xaml

<Window x:Class="WpfTestApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfTestApp" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <StackPanel Orientation="Vertical"> <local:TestUserControl TextFromParent="{Binding SomeText}" /> <TextBlock Name="TestTextBlock" Text="{Binding SomeText}" /> </StackPanel> </Window>

MainWindow.xaml.cs

using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; namespace WpfTestApp { public partial class MainWindow : Window, INotifyPropertyChanged { private string _someText; public MainWindow() { DataContext = this; InitializeComponent(); SomeText = "New Text!"; } public string SomeText { get { return _someText; } set { _someText = value; NotifyOnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected void NotifyOnPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }

TestUserControl.xaml

<UserControl x:Class="WpfTestApp.TestUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WpfTestApp" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <Grid> <TextBlock Name="TheTextBlock" Text="{Binding TextFromParent}" /> </Grid> </UserControl>

TestUserControl.xaml.cs

using System.Windows; using System.Windows.Controls; namespace WpfTestApp { public partial class TestUserControl : UserControl { public TestUserControl() { InitializeComponent(); } public string TextFromParent { get { return (string)GetValue(TextFromParentProperty); } set { SetValue(TextFromParentProperty, value); } } public static readonly DependencyProperty TextFromParentProperty = DependencyProperty.Register( "TextFromParent", typeof(string), typeof(TestUserControl), new PropertyMetadata()); } }

El programa se ve como el siguiente cuando se ejecuta, el primer texto está en blanco seguido de TextBlock con enlace de trabajo:


El UserControl realmente hereda el DataContext de su elemento padre. Sin embargo, no TextFromParent propiedad TextFromParent en ese DataContext (porque es la instancia de MainWindow).

Se supone que la vinculación en el XAML de UserControl se vincula a una propiedad del UserControl en sí, no a uno de los DataContext actuales. Por lo tanto, debe usar la instancia de UserControl como objeto fuente:

<TextBlock Text="{Binding TextFromParent, RelativeSource={RelativeSource AncestorType=UserControl}}" />

Establecer el DataContext de UserControl para sí mismo no es una opción, porque impide que un valor DataContext se herede del elemento padre del control.

Sin embargo, puede establecer el DataContext del elemento raíz en el XAML de UserControl para evitar establecer RelativeSource en potencialmente muchos enlaces:

<UserControl ...> <Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"> <TextBlock Text="{Binding TextFromParent}" /> </Grid> </UserControl>