閱讀更新以獲取解決方案
我有一個小型 WPF 應用程式,其中包含多個小型游戲克隆,例如 Minesweeper、Connect 4、Tic Tac Toe 等。
所有這些的共同點是它們都是一個統一的方格,每個方格都由一個按鈕控制。
對于這些游戲中的每一個,我都在其 XAML 中定義了一個帶有 UniformGrid ItemsPanelTemplate 的 UserControl。
它們唯一不同的地方是使用的 DataTemplate:
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- Button that fit the specific need of the game -->
</DataTemplate>
</ItemsControl.ItemTemplate>
為了避免重復,我想創建一個具有 DataTemplate 依賴屬性的 UserControl(并且在名為 itemscontrol 的 XAML 中定義了一個 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 來根據情況簡單地接受不同的 Button?
更新
我結合了我標記為已接受的解決方案和@Joe 在這篇文章中的評論。
我創建了一個具有所需屬性的自定義控制元件,而不是 UserControl,然后根據我的喜好在 Generic.xaml 檔案中設定樣式。我還從自定義控制元件中洗掉了 DataTemplate 屬性,而是在我的 App.xaml 中為每個不同的 VM 添加了 DataTemplates。
您將在下面找到我的新自定義控制元件背后的代碼和樣式。
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,其中存盤了 Square View 模型。
資料模板示例
<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>
uj5u.com熱心網友回復:
如果我正確理解您的需求,那么您需要稍微更改實作:您不應該在代碼隱藏中使用值賦值 - 相反,您需要在 XAML 中使用系結。
public BoardGameControl()
{
InitializeComponent();
// itemscontrol.ItemTemplate = DataTemplate;
}
<ItemsControl ItemTemplate="{Binding DataTemplate, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:BoardGameControl}}}">
我也強烈建議在這種情況下(當屬性被添加到一個元素,它的行為發生變化等)不要使用 UserControl,而是使用自定義控制元件。
為什么我的實施不起作用?
夏普的實作:
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;
}
我會制作一個自定義控制元件,但是我不知道如何自己實作 ItemsControl / UniformGrid 的邏輯
如果您在 Studio 中作業,則在背景關系選單中選擇“添加”->“創建元素”。將出現一個組合框并從中選擇“自定義控制元件 WPF”。您將擁有從 Control 派生的類代碼。添加屬性和你需要的行為邏輯。并且還將創建“Themes/Generic.xaml”檔案 - 這是默認主題。此主題將為您的元素提供一個模板 - 根據需要對其進行編輯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/506311.html
