I am writing a custom control, in a template containing a ListBox with overridden ItemTemplate templates. The type of collection objects is not known in advance. How to bind an ItemTemplate so that it displays the class field specified in DisplayMemberPath?

<ListBox ItemsSource="{TemplateBinding SelectedItems}" DisplayMemberPath="{TemplateBinding DisplayMemberPath}"> <ListBox.ItemTemplate> <DataTemplate> <Label Content="{Binding /*какое выражение?*/}"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox> 
  • Usually DisplayMemberPath not used if there is an ItemTemplate , ItemTemplate they conflict. stackoverflow.com/a/7486992/276994 Tell better what is the real task before you. - VladD
  • The task is to write a control based on XamComboEditor (Infragistics). In the control, in the AllowMultipleSelection="True" mode, there should be a panel displaying the collection of selected elements in the form of labels, labels with a cross. When you click on the cross, the selection of the element should be removed. To implement, I took a ListBox , redefined the ItemsPanelTemplate template. Replaced the standard on the WrapPanel . Also redefined ItemTemplate - interposed StackPanel with Label and Button . Since the type of the elements of the collection is not known, I can not bind Label.Content to correctly display the necessary information. - xlmax
  • VladD, told above. - xlmax

1 answer 1

Figured! It was not so easy.

So, the idea: we create a control that will set up the necessary DataContext its child element. We do so. First, create a custom control:

 [Localizability(LocalizationCategory.Ignore, Readability = Readability.Unreadable)] [ContentProperty("Content")] public class DisplayMemberPathPropagator : Control { static DisplayMemberPathPropagator() { DefaultStyleKeyProperty.OverrideMetadata( typeof(DisplayMemberPathPropagator), new FrameworkPropertyMetadata(typeof(DisplayMemberPathPropagator))); } #region dp string DisplayMemberPath, on change SetBinding for InnerDataContext public string DisplayMemberPath { get { return (string)GetValue(DisplayMemberPathProperty); } set { SetValue(DisplayMemberPathProperty, value); } } public static readonly DependencyProperty DisplayMemberPathProperty = DependencyProperty.Register( "DisplayMemberPath", typeof(string), typeof(DisplayMemberPathPropagator), new PropertyMetadata(null, (o, args) => { var self = (DisplayMemberPathPropagator)o; self.SetBinding(InnerDataContextProperty, (string)args.NewValue); })); #endregion #region dp object InnerDataContext public object InnerDataContext { get { return (object)GetValue(InnerDataContextProperty); } set { SetValue(InnerDataContextProperty, value); } } public static readonly DependencyProperty InnerDataContextProperty = DependencyProperty.Register( "InnerDataContext", typeof(object), typeof(DisplayMemberPathPropagator)); #endregion #region dp UIElement Content public UIElement Content { get { return (UIElement)GetValue(ContentProperty); } set { SetValue(ContentProperty, value); } } public static readonly DependencyProperty ContentProperty = DependencyProperty.Register( "Content", typeof(UIElement), typeof(DisplayMemberPathPropagator)); #endregion } 

and define the style for it in Themes \ Generic.xaml:

 <Style TargetType="{x:Type local:DisplayMemberPathPropagator}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:DisplayMemberPathPropagator}"> <ContentControl Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" DataContext="{TemplateBinding InnerDataContext}" Content="{TemplateBinding Content}"/> </ControlTemplate> </Setter.Value> </Setter> </Style> 

Now you can use it:

 <ListBox ItemsSource="{TemplateBinding SelectedItems}" Tag="{TemplateBinding DisplayMemberPath}"> <ListBox.ItemTemplate> <DataTemplate> <local:DisplayMemberPathPropagator DisplayMemberPath="{Binding Tag, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}"> <Label Content="{Binding}"/> </local:DisplayMemberPathPropagator> </DataTemplate> </ListBox.ItemTemplate> </ListBox> 

Try it!