如何将DataTemplate注入WPF自定义Style/UserControl实现棋盘复用?
查看更新获取解决方案
我开发了一个小型WPF应用,包含扫雷、四子棋、井字棋等多款小游戏的克隆版。
这些游戏的共同特点是都由统一网格的方块组成,每个方块由按钮控制。
我为每个游戏都定义了一个UserControl,其XAML中包含UniformGrid类型的ItemsPanelTemplate。
它们唯一的区别在于所使用的DataTemplate:
<ItemsControl.ItemTemplate> <DataTemplate> <!-- 满足游戏特定需求的按钮 --> </DataTemplate> </ItemsControl.ItemTemplate>
为避免重复代码,我希望创建一个带有DataTemplate依赖属性的UserControl(其XAML中定义了名为itemscontrol的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; }
我尝试在应用中这样使用它:
<controls:BoardGameControl> <controls:BoardGameControl.DataTemplate> <DataTemplate> <Button Content="Hi"/> </DataTemplate> </controls:BoardGameControl.DataTemplate> </controls:BoardGameControl>
我还尝试了其他方法,但都没成功。
如何避免为每个游戏定义新的ItemsControl,转而使用可根据场景适配不同按钮的UserControl或Style?
更新
我结合了标记为已采纳的解决方案和@Joe的评论。
我没有使用UserControl,而是创建了一个带有所需属性的自定义控件,并在Generic.xaml文件中为其设置样式。我还移除了自定义控件中的DataTemplate属性,改为在App.xaml中为每个不同的视图模型添加DataTemplate。
以下是我的新自定义控件的后台代码和样式:
public class GameBoardControl : Control { public int Columns { get => (int)GetValue(ColumnsProperty); set => SetValue(ColumnsProperty, value); } public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register(nameof(Columns), typeof(int), typeof(BoardGameControl)); public int Rows { get => (int)GetValue(RowsProperty); set => SetValue(RowsProperty, value); } public static readonly DependencyProperty RowsProperty = DependencyProperty.Register(nameof(Rows), typeof(int), typeof(BoardGameControl)); static GameBoardControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(GameBoardControl), new FrameworkPropertyMetadata(typeof(GameBoardControl))); } }
<Style TargetType="{x:Type controls:GameBoardControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type controls:GameBoardControl}"> <ItemsControl ItemsSource="{Binding Squares}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <UniformGrid Columns="{Binding Columns, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:GameBoardControl}}}" Rows="{Binding Rows, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:GameBoardControl}}}"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl> </ControlTemplate> </Setter.Value> </Setter> </Style>
请注意,我始终将ItemsSource绑定到Squares,因为所有游戏都有一个名为Squares的ObservableCollection,用于存储方块视图模型。
DataTemplate示例:
<DataTemplate DataType="{x:Type mvvmtoolkit:MemorySquareVM}"> <Button Command="{Binding RelativeSource={RelativeSource AncestorType=controls:GameBoardControl}, Path=DataContext.PressSquareCommand}" CommandParameter="{Binding}" Background="{Binding Position, Converter={local:PositionToColorConverter}}" Style="{StaticResource MemoryButton}"/> </DataTemplate>
内容的提问来源于stack exchange,提问作者Silop
相关产品推荐
相关产品推荐

