I have a small WPF Application with several small game clones such as Minesweeper, Connect 4, Tic Tac Toe among others.
Common for all of these is that they are all a uniform grid of squares, each square is controlled by a button.
For each of these games I have defined a UserControl with a UniformGrid ItemsPanelTemplate in their XAML.
The only place they differ is the DataTemplate used:
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- Button that fit the specific need of the game -->
</DataTemplate>
</ItemsControl.ItemTemplate>
To avoid repetition I wanted to create a UserControl which has a DataTemplate dependency property (and has an ItemsControl defined in the XAML named itemscontrol):
public DataTemplate DataTemplate
{
get => (DataTemplate)GetValue(DataTemplateProperty);
set => SetValue(DataTemplateProperty, value);
}
public static readonly DependencyProperty DataTemplateProperty =
DependencyProperty.Register("DataTemplate", typeof(DataTemplate), typeof(BoardGameControl));
public BoardGameControl()
{
InitializeComponent();
itemscontrol.ItemTemplate = DataTemplate;
}
Which I tried to use in my application like so:
<controls:BoardGameControl>
<controls:BoardGameControl.DataTemplate>
<DataTemplate>
<Button Content="Hi"/>
</DataTemplate>
</controls:BoardGameControl.DataTemplate>
</controls:BoardGameControl>
I have tried some other approaches as well but none have worked.
How can I avoid having to define a new ItemsControl for each game and instead have a UserControl or Style that simply accepts a different Button depending on the situation?
CodePudding user response:
If I understand correctly what you need, then you need to slightly change the implementation: You should not use value assignment in Code Behind - Instead, you need to use binding in XAML.
public BoardGameControl()
{
InitializeComponent();
// itemscontrol.ItemTemplate = DataTemplate;
}
<ItemsControl ItemTemplate="{Binding DataTemplate, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:BoardGameControl}}}">
I also strongly advise in such cases (when properties are added to an element, its behavior is changed, etc.) to use not UserControl, but Custom Control.
why my implementation did not work?
Implementation on Sharp:
public static readonly DependencyProperty DataTemplateProperty =
DependencyProperty.Register("DataTemplate", typeof(DataTemplate), typeof(BoardGameControl),
new PropertyMetadata((d, e) => ((BoardGameControl)d).itemscontrol.ItemTemplate = (IEnumerable) e.NewValue));
public BoardGameControl()
{
InitializeComponent();
// itemscontrol.ItemTemplate = DataTemplate;
}
I would make a Custom Control, however I do not know how to implement the logic of an ItemsControl / UniformGrid myself
If you work in the Studio, then select "Add" -> "Create element" in the context menu. A combo box will appear and select "Custom Control WPF" from it. You will have a class code derived from Control. Add properties and the logic of behavior you need to it. And the "Themes/Generic.xaml" file will also be created - this is the default theme. This theme will have a template for your element - edit it as you need.