So when I use the below style, it is applied to my control as expected. However, the templates inside of the GridView (ItemsPanelTemplate and ItemsTemplate) look at the view model the consumer applies for its data context.
The problem is that I want to set the item dimensions in my control.
So my question is, how do I apply the control template as the data context to the ItemsPanelTemplate and the ItemTemplate?
My first thought was to use ancestral binding but that doesn't appear to be a feature in UWP.
My Control Class
public class FilterableImageWrapGrid : FilterableContentList
{
private GridView _partGridView;
public Point ItemDimensions
{
get { return (Point)GetValue(ItemDimensionsProperty); }
set { SetValue(ItemDimensionsProperty, value); }
}
// Using a DependencyProperty as the backing store for ItemDimensions. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemDimensionsProperty =
DependencyProperty.Register("ItemDimensions", typeof(Point), typeof(FilterableImageWrapGrid), new PropertyMetadata(new Point()));
public FilterableImageWrapGrid()
{
DefaultStyleKey = typeof(FilterableImageWrapGrid);
}
protected override void OnApplyTemplate()
{
_partGridView = GetTemplateChild("PART_FilterableImageList") as GridView;
base.OnApplyTemplate();
}
private static void OnItemDimensionsChanged(object sender, DependencyPropertyChangedEventArgs args)
{
FilterableImageWrapGrid wrapGrid = sender as FilterableImageWrapGrid;
if (wrapGrid != null && wrapGrid._partGridView != null)
{
wrapGrid._partGridView.ItemTemplate.SetValue(GridViewItem.WidthProperty, wrapGrid.ItemDimensions.X);
wrapGrid._partGridView.ItemTemplate.SetValue(GridViewItem.HeightProperty, wrapGrid.ItemDimensions.Y);
}
}
}
My style in my Generic.xaml file
<Style TargetType="controls:FilterableImageWrapGrid">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid VerticalAlignment="Stretch">
<GridView
x:Name="PART_FilterableImageList"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=FilteredItems, Mode=TwoWay}"
SelectedItem="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=SelectedContentItem, Mode=TwoWay}">
<GridView.ItemContainerTransitions>
<TransitionCollection>
<EntranceThemeTransition IsStaggeringEnabled="True"/>
<AddDeleteThemeTransition />
<EdgeUIThemeTransition Edge="Left"/>
</TransitionCollection>
</GridView.ItemContainerTransitions>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid
x:Name="PART_ItemsWrapGrid"
ItemHeight="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ItemDimensions.Y}"
ItemWidth="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ItemDimensions.X}"
Margin="2" Orientation="Horizontal"
HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate>
.... Data template that binds to the view model the consumer provides....
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If I understand you correctly it doesn't work to have the RelativeSource Mode=TemplatedParent binding in a template inside a template. Is that it?
then define the ItemDimensions property as an attached Dependency Property:
public class FilterableImageWrapGrid : FilterableContentList
public static Point GetItemDimensions(DependencyObject obj)
{
return (Point)obj.GetValue(ItemDimensionsProperty);
}
public static void SetItemDimensions(DependencyObject obj, Point value)
{
obj.SetValue(ItemDimensionsProperty, value);
}
public static readonly DependencyProperty ItemDimensionsProperty =
DependencyProperty.RegisterAttached("ItemDimensions", typeof(Point), typeof(ItemsWrapGrid), new PropertyMetadata(new Point()));
...
}
and then add this to the template:
<GridView
x:Name="PART_FilterableImageList"
...
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid
x:Name="PART_ItemsWrapGrid"
ItemHeight="{Binding RelativeSource=
{RelativeSource Mode=Self}, Path=ItemDimensions.Y}"
ItemWidth="{Binding RelativeSource=
{RelativeSource Mode=Self}, Path=ItemDimensions.X}"
Margin="2" Orientation="Horizontal"
HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
...
</GridView>
That would be like an inheritable property (which don't exist in uwp (yet?)) that you manually push downward the visual tree to the inner template with the template binding.
Related
Background
I am making a custom control that has multiple ListBox's. I want to make this control MVVM compliant, so I am keeping any XAML and the code behind agnostic with respect to any ViewModel. One ListBox is simply going to be a list of TextBox's while the other is going to have a canvas as the host to display the data graphically. Both of these ListBox's are children of this custom control.
Pseudo example for the custom control template:
<CustomControl>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox1 Grid.Column="0"/>
<ListBox2 Grid.Column="1"/>
</CustomControl>
The code behind for this custrom control would have a dependency property that will serve as the ItemsSource, fairly standard stuff:
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(UserControl1), new PropertyMetadata(new PropertyChangedCallback(OnItemsSourcePropertyChanged)));
private static void OnItemsSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var control = sender as UserControl1;
if (control != null)
control.OnItemsSourceChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue);
}
Where I am stuck
Because the two ListBox's are using the same data source but just display the data differently, I want the ItemsSource defined as one of the the parent view's dependency properties to be the ItemsSource for the two children. From the ViewModel side, this items source can be some sort of ObservableCollection<ChildViewModels>, or IEnumerable, or whatever it wants to be.
How can I point to properties from the ItemsSource's ViewModel to dependency properties of the child views?
I was hoping to get something similar to how it could be done outside of a custom view:
Example Parent ViewModel(omitting a lot, assume all functioning):
public class ParentViewModel
{
public ObservableCollection<ChildViewModel> ChildViewModels;
}
Example ViewModel (omitting INotifyPropertyChanged and associated logic):
public class ChildViewModel
{
public string Name {get; set;}
public string ID {get; set;}
public string Description {get; set;}
}
Example control (ommitting setting the DataContext, assume set properly):
<ListBox ItemsSource="{Binding ChildViewModels}">
<ListBox.ItemsTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text ="{Binding Description}"/>
</StackPanel>
</ListBox.ItemsTemplate>
</ListBox>
How can I do something similar where I can pass the properties from the ItemsSource to the child views on a custom control?
Many thanks
If I understand correctly what you need, then here is an example.
Add properties for element templates in both lists and style for Canvas.
using System.Collections;
using System.Windows;
using System.Windows.Controls;
namespace Core2022.SO.jgrmn
{
public class TwoListControl : Control
{
static TwoListControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TwoListControl), new FrameworkPropertyMetadata(typeof(TwoListControl)));
}
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register(
nameof(ItemsSource),
typeof(IEnumerable),
typeof(TwoListControl),
new PropertyMetadata((d, e) => ((TwoListControl)d).OnItemsSourceChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue)));
private void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
//throw new NotImplementedException();
}
public DataTemplate TemplateForStack
{
get { return (DataTemplate)GetValue(TemplateForStackProperty); }
set { SetValue(TemplateForStackProperty, value); }
}
public static readonly DependencyProperty TemplateForStackProperty =
DependencyProperty.Register(
nameof(TemplateForStack),
typeof(DataTemplate),
typeof(TwoListControl),
new PropertyMetadata(null));
public DataTemplate TemplateForCanvas
{
get { return (DataTemplate)GetValue(TemplateForCanvasProperty); }
set { SetValue(TemplateForCanvasProperty, value); }
}
public static readonly DependencyProperty TemplateForCanvasProperty =
DependencyProperty.Register(
nameof(TemplateForCanvas),
typeof(DataTemplate),
typeof(TwoListControl),
new PropertyMetadata(null));
public Style StyleForCanvas
{
get { return (Style)GetValue(StyleForCanvasProperty); }
set { SetValue(StyleForCanvasProperty, value); }
}
public static readonly DependencyProperty StyleForCanvasProperty =
DependencyProperty.Register(
nameof(StyleForCanvas),
typeof(Style),
typeof(TwoListControl),
new PropertyMetadata(null));
}
}
In the theme (Themes/Generic.xaml), set bindings to these properties:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:jgrmn="clr-namespace:Core2022.SO.jgrmn">
<Style TargetType="{x:Type jgrmn:TwoListControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type jgrmn:TwoListControl}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0"
ItemsSource="{TemplateBinding ItemsSource}"
ItemTemplate="{TemplateBinding TemplateForStack}"/>
<ListBox Grid.Column="1"
ItemsSource="{TemplateBinding ItemsSource}"
ItemTemplate="{TemplateBinding TemplateForCanvas}"
ItemContainerStyle="{TemplateBinding StyleForCanvas}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Window with an example of use:
<Window x:Class="Core2022.SO.jgrmn.TwoListWindow"
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:Core2022.SO.jgrmn"
mc:Ignorable="d"
Title="TwoListWindow" Height="250" Width="400">
<FrameworkElement.DataContext>
<CompositeCollection>
<Point>15 50</Point>
<Point>50 150</Point>
<Point>150 50</Point>
<Point>150 150</Point>
</CompositeCollection>
</FrameworkElement.DataContext>
<Grid>
<local:TwoListControl ItemsSource="{Binding}">
<local:TwoListControl.TemplateForStack>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}Point ({0} {1})">
<Binding Path="X"/>
<Binding Path="Y"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</local:TwoListControl.TemplateForStack>
<local:TwoListControl.TemplateForCanvas>
<DataTemplate>
<Ellipse Width="10" Height="10" Fill="Red"/>
</DataTemplate>
</local:TwoListControl.TemplateForCanvas>
<local:TwoListControl.StyleForCanvas>
<Style TargetType="ListBoxItem">
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</local:TwoListControl.StyleForCanvas>
</local:TwoListControl>
</Grid>
</Window>
You must spend all participating controls a ItemsSource property. The idea is to delegate the source collection from the parent to the child controls and finally to the ListBox. The ItemsSource properties should be a dependency property of type IList and not IEnumerable. This way you force the binding source to be of type IList which improves the binding performance.
To allow customization of the actual displayed items, you must either
a) spend every control a ItemTemplate property of type DataTemplate and delegate it to the inner most ListBox.ItemTemplate (similar to the ItemsSource property) or
b) define the template as a resource (implicit template, which is a key less DataTemplate).
The example implements a):
<Window>
<Window.DataContext>
<ParentViewModel />
</Window.DataCOntext>
<CustomControl ItemsSource="{Binding ChildViewModels}">
<CustomControl.ItemsTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text ="{Binding Description}"/>
</StackPanel>
</CustomControl.ItemsTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox1 Grid.Column="0"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ItemsSource}"
ItemTemplate="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ItemTemplate}" />
<ListBox2 Grid.Column="1"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ItemsSource}"
ItemTemplate="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ItemTemplate}" />
</CustomControl>
</Window>
Inside the child controls (ListBox1 and ListBox2):
<UserControl>
<ListBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ItemsSource}"
ItemTemplate="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ItemTemplate}" />
</UserControl>
I use a DataGrid in my WPF application. It does feature RowDetails for selected Rows. Therefor I set the RowDetailsTemplate. Inside this DataTemplate i want to access my Window's DataContext. For Example I have a lable inside my RowDetailsTemplate and I want to bind it's content-property to a property of my viewModel which is in the DataContext of the window. How do I achieve this.
Thank you for your help!
Look at this usage of RelativeSource based binding, like {Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}. Here is example:
Xaml:
<DataGrid ItemsSource="{Binding Strings}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTemplateColumn Header="String" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type soDataGridHeplAttempt:ClicableItemsModel}">
<ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding ClickableItems}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Button Width="70" Content="{Binding }" Style="{StaticResource ButtonInCellStyle}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=DataContext.Command}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Content}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
View model:
private ICommand _command;
public ObservableCollection<ClicableItemsModel> Strings { get; set; }
public ICommand Command
{
get { return _command ?? (_command = new RelayCommand<object>(MethodOnCommmand)); }
}
private void MethodOnCommmand(object obj)
{
}
Model pu this inside the the model class:
public ObservableCollection<String> ClickableItems { get; set; }
regards,
I have following control template:
public sealed partial class ItemSelectorControl : Control
{
...
public ICommand SelectionCommand
{
get { return (ICommand)GetValue(SelectionCommandProperty); }
set { SetValue(SelectionCommandProperty, value); }
}
public static readonly DependencyProperty SelectionCommandProperty =
DependencyProperty.Register("SelectionCommand", typeof(ICommand), typeof(ItemSelectorControl), new PropertyMetadata(null));
public ItemSelectorControl()
{
DefaultStyleKey = typeof(ItemSelectorControl);
}
...
}
and the corresponding theme style:
<Style TargetType="controls:ItemSelectorControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:ItemSelectorControl">
<Grid>
<StackPanel Orientation="Vertical">
<TextBlock
Style="{StaticResource SectionHeader}"
Text="{TemplateBinding Headline}"
Visibility="{TemplateBinding HeadlineVisibility}"/>
<ItemsControl
x:Name="CurrencyItemPanel"
ItemsSource="{TemplateBinding ItemCollection}"
MaxHeight="{TemplateBinding MaximumItemsControlHeight}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Style="{StaticResource ItemSelectorButtonStyle}"
Command="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=SelectionCommand}"
CommandParameter="{Binding Path=Code}">
<interactivity:Interaction.Behaviors>
<behaviour:ItemSelectorVisualStateBehaviour
StateChangeTrigger="{Binding Selected, Mode=TwoWay}"/>
</interactivity:Interaction.Behaviors>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How do I have to write the command binding?
Command="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=SelectionCommand}"
In WPF I would work with FindAncestor but since that is not available in WinRT I don't not how to bind? I can't use DataContext.SelectionCommand because the current DataContext is the ViewModel.
I have a problem when I try to bind a int value to a DependencyProperty in a custom control from a style.
MyClassVM contains an int named Number. It shows perfectly in the Label, when I bind in the same way, but will not set on my custom control. If I change from "{Binding Number}" To "15" for example, everything works great also on the custom control.
<Style TargetType="{x:Type ItemsControl}" x:Key="TestKey">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ItemsPresenter />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Style.Resources>
<DataTemplate DataType="{x:Type local:MyClassVM}">
<StackPanel Orientation="Horizontal">
<StackPanel.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding DataContext.OpenProjectCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" CommandParameter="{Binding .}" />
</StackPanel.InputBindings>
<ctrl:MyCustomControl Margin="5" Width="50" ctrl:MyCustomControl.ValueProperty="{Binding Number}"/>
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Number}" FontSize="14" Foreground="{DynamicResource CeriseBrush}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</Style.Resources>
</Style>
This is how the MyCustomControl-class looks.
public partial class MyCustomControl: CustomUserControl
{
public int Value { get { return _value; } set { _value = value; } }
public MyCustomControl()
{
InitializeComponent();
DataContext = this;
}
public string ValueProperty
{
get { return (string)GetValue(ValuePropertyProperty); }
set { SetValue(ValuePropertyProperty, value); }
}
public static readonly DependencyProperty ValuePropertyProperty =
DependencyProperty.Register("ValueProperty", typeof(int), typeof(MyCustomControl), new UIPropertyMetadata(ValuePropertyChangedHandler));
public static void ValuePropertyChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
((MyCustomControl)sender).Value = (int)e.NewValue;
}
}
The error I get looks like this:
System.Windows.Data Error: 40 : BindingExpression path error: 'Number' property not found on 'object' ''MyCustomControl' (Name='')'. BindingExpression:Path=Number; DataItem='MyCustomControl' (Name=''); target element is 'MyCustomControl' (Name=''); target property is 'ValueProperty' (type 'Int32')
Not sure, but I think you have to provide a relative source in your binding like:
Label Content="{Binding Number, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
Replace Window with UserControl if you're in a Control
I would like to bind an element inside a control template for a custom control to a property defined in a child class defined inside the custom control class. What might be the syntax for doing that (see {Binding ???})?
Some code...
C# code:
public class CustmCntrl : Control
{
// blablabla
public class SubChildClass: INotifyPropertyChanged
{
public double X { get; private set; }
public string info { get; private set; }
}
}
XAML:
<Style TargetType="{x:Type local:CustmCntrl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustmCntrl}">
<Grid> ... </Grid>
<ItemsControl
ItemsSource="{Binding stuffToDisplay, RelativeSource={RelativeSource TemplatedParent}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate >
<Grid> ... </Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:X
ToolTip="{Binding info ???}">
<local:X.RenderTransform>
<TranslateTransform X="{Binding X ???}"/>
</local:X.RenderTransform>
</local:X>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I can't test this at the moment, but you should be able to bind by adding the name of the SubChildClass class. Try something like this:
<TextBlock Text="{Binding SubChildClass.PropertyName, RelativeSource={RelativeSource
AncestorType={x:Type YourPrefix:YourCustomControl}}}">
If that doesn't work, try this:
<TextBlock Text="{Binding (SubChildClass.PropertyName), RelativeSource={RelativeSource
AncestorType={x:Type YourPrefix:YourCustomControl}}}">
You can find out more from the Property Path Syntax page on MSDN.
UPDATE >>>
Yeah, after getting a chance to test this out in a project, it seems that you can't data bind directly with class properties like that. However, if you just wanted to declare the class there as a container for some basic data items in your control then that is fine. As long as you define some DependencyPropertys to hold them, you can use that class just fine:
private static DependencyProperty ItemsProperty = DependencyProperty.Register("Items",
typeof(ObservableCollection<SubChildClass>), typeof(CustomControl1));
public ObservableCollection<SubChildClass> Items
{
get { return (ObservableCollection<SubChildClass>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
In Generic.xaml:
<ListBox ItemsSource="{Binding Items,
RelativeSource={RelativeSource AncestorType={x:Type local:CustmCntrl}}}" />