c# wpf data-binding custom-controls itemscontrol

c# - Enlace a control personalizado dentro de DataTemplate para ItemsControl



wpf data-binding (1)

El problema es que establece explícitamente el DataContext de su UserControl en sí mismo:

DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}

Elimine esa asignación y escriba el enlace ItemName esta manera:

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

o así

<TextBlock Text="{Binding ItemName, ElementName=ItemRowControl}"/>

Tengo un problema con los enlaces para DataTemplate basado en DataType definido en ItemsControl , cuando quiero enlazar a mi control de usuario personalizado .

Para fines de demostración, he creado un ejemplo de clase de elemento simple, donde tengo una colección de elementos como este:

public class Item { public string ItemNameToBeSureWhatPropertyIsBound { get; set; } }

En mi ViewModel, creo dicha colección y la expongo (con un elemento para comparar por separado):

public class MainWindowViewModel : INotifyPropertyChanged { private ObservableCollection<Item> _items; private Item _exampleItem; public MainWindowViewModel() { Items = new ObservableCollection<Item>(new[] { new Item { ItemNameToBeSureWhatPropertyIsBound = "Me" }, new Item { ItemNameToBeSureWhatPropertyIsBound = "MySelf" }, new Item { ItemNameToBeSureWhatPropertyIsBound = "Ich" }, }); ExampleItem = Items.LastOrDefault(); } public ObservableCollection<Item> Items { get { return _items; } set { _items = value; OnPropertyChanged(); } } public Item ExampleItem { get { return _exampleItem; } set { _exampleItem = value; OnPropertyChanged();} } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } }

Mi control de usuario personalizado se define así:

<UserControl x:Class="WpfDataTemplate.ItemRowUserControl" 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" mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="300" x:Name="ItemRowControl" DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}"> <Grid Background="Yellow" Height="40"> <TextBlock Text="{Binding ItemName}" Foreground="Black"/> </Grid> </UserControl>

... y tiene una DependencyProperty en el código detrás :

public partial class ItemRowUserControl : UserControl { public ItemRowUserControl() { InitializeComponent(); } public static readonly DependencyProperty ItemNameProperty = DependencyProperty.Register( "ItemName", typeof (string), typeof (ItemRowUserControl), new PropertyMetadata(default(string))); public string ItemName { get { return (string) GetValue(ItemNameProperty); } set { SetValue(ItemNameProperty, value); } } }

El problema es que cuando intento vincularme a la propiedad de Item en DataTemplate para ItemsControl, lo que estoy haciendo en MainWindow de esta manera (nota: tengo un convertidor ficticio solo para fines de depuración, devolviendo el valor y nada más):

<Window.DataContext> <my:MainWindowViewModel /> </Window.DataContext> <Window.Resources> <my:MyDummyConverter x:Key="MyDummyConverter" /> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="50" /> </Grid.RowDefinitions> <ItemsControl Name="ItemsControl" ItemsSource="{Binding Items}" Grid.Row="0" Background="Red"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate DataType="{x:Type my:Item}"> <my:ItemRowUserControl ItemName="{Binding ItemNameToBeSureWhatPropertyIsBound, Converter={StaticResource MyDummyConverter}}" /> <!--<Grid Background="Pink"> <TextBlock Text="{Binding ItemNameToBeSureWhatPropertyIsBound, Converter={StaticResource MyDummyConverter}}" Foreground="Black" Height="30" /> </Grid>--> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <Grid Grid.Row="1"> <my:ItemRowUserControl ItemName="{Binding DataContext.ExampleItem.ItemNameToBeSureWhatPropertyIsBound, ElementName=MyWindow, Converter={StaticResource MyDummyConverter}}" /> </Grid> </Grid>

Ahora, en caso de que me enlace a mi ItemRowUserControl personalizado, el valor que obtengo en el convertidor (y veo lo mismo en la Salida de depuración) es el propio ItemRowUserControl. Pero si me ato al código comentado, todo funciona bien. ¿Por qué es eso y cómo puedo tener un control personalizado para DataTemplate para que funcionen los enlaces (ofrecidos por intellisense)? En la nota al margen: el enlace a mi ItemRowUserControl en la fila 1 de la cuadrícula (en la parte inferior) funciona bien, ¿así que supongo que el control está configurado para funcionar como se esperaba?