Wpf 重新思考控制继承

Wpf 重新思考控制继承,wpf,inheritance,binding,Wpf,Inheritance,Binding,我正在编写一个应用程序,从XML文件加载记录并使用它们填充表单。它是用于纸牌游戏的,因此我希望表单显示不同的字段,并根据特定记录(具体取决于记录中的“CardType”字段)具有不同的外观 在vanilla C#中,我将创建一个包含记录的基本窗口,然后为每个特定类型从中继承,从而更改窗口的视觉效果。然后检查类型,实例化正确的窗口并填充它 在WPF中,不允许从窗口继承,因此解决方案是使用单个窗口,然后根据情况使用样式/模板来调整窗口 最初,我创建了完全独立的窗口,将适当的窗口传递给一个类,该类保存

我正在编写一个应用程序,从XML文件加载记录并使用它们填充表单。它是用于纸牌游戏的,因此我希望表单显示不同的字段,并根据特定记录(具体取决于记录中的“CardType”字段)具有不同的外观

在vanilla C#中,我将创建一个包含记录的基本窗口,然后为每个特定类型从中继承,从而更改窗口的视觉效果。然后检查类型,实例化正确的窗口并填充它

在WPF中,不允许从窗口继承,因此解决方案是使用单个窗口,然后根据情况使用样式/模板来调整窗口

最初,我创建了完全独立的窗口,将适当的窗口传递给一个类,该类保存用于设置DataContext的记录数据

然而,现在我正在努力把事情做好,我正在努力掌握确切的方法。我尝试在样式中创建一个控件模板,其中包含用于保存字段的控件,并使用绑定填充字段

    <Style TargetType="{x:Type Label}" x:Key="testLabel">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Label}">
                    <Grid>
                        <Rectangle Fill="White" Stroke="Black" StrokeThickness="3" RadiusX="20" RadiusY="20" />
                        <DockPanel LastChildFill="False" Margin="10">
                            <DockPanel DockPanel.Dock="Top">
                                <Grid VerticalAlignment="Top" DockPanel.Dock="Left">
                                    <Ellipse Height="25" Width="25" Stroke="Black" StrokeThickness="2" Fill="Red"/>
                                    <TextBlock Name="textLevel" Foreground="Black" FontSize="15" TextAlignment="Center" VerticalAlignment="Center" Text="{Binding Level, UpdateSourceTrigger=PropertyChanged}"/>
                                </Grid>
                                <DockPanel DockPanel.Dock="Top">
                                    <TextBlock Name="textType" Foreground="Black" FontSize="15" FontWeight="Bold" FontStyle="Italic" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10, 0, 10, 0" DockPanel.Dock="Right" Text="{Binding CardType, UpdateSourceTrigger=PropertyChanged}"/>       
                                    <TextBlock Name="textName" Foreground="Black" FontSize="20" FontWeight="Bold" Margin="10, 0, 10, 0" DockPanel.Dock="Left" Text="{Binding CardName, UpdateSourceTrigger=PropertyChanged}"/>      
                                </DockPanel>
                                <TextBlock Name="textPronounciation" Foreground="DarkSlateGray" FontSize="12" Margin="10, 0, 10, 0" DockPanel.Dock="Top" Text="{Binding Pronounciation, UpdateSourceTrigger=PropertyChanged}"/>
                            </DockPanel>
                            <Rectangle Name="rectPicture" Width="280" Height="210" Margin="0, 5" DockPanel.Dock="Top"/>
                            <TextBlock Name="textLineage" Foreground="Black" FontSize="15" Margin="10, 0, 10, 0" DockPanel.Dock="Top" Text="{Binding Lineage, UpdateSourceTrigger=PropertyChanged}"/>
                            <TextBlock Name="textFlavourText" Foreground="Black" FontSize="11" TextWrapping="Wrap" Margin="10, 0, 10, 0" DockPanel.Dock="Top" Text="{Binding FlavourText, UpdateSourceTrigger=PropertyChanged}"/>
                            <TextBlock Name="textQuote" Foreground="Black" FontSize="11" TextWrapping="Wrap" Margin="10, 5, 10, 0" DockPanel.Dock="Top" Text="{Binding Quote, UpdateSourceTrigger=PropertyChanged}"/>
                            <TextBlock Name="textAttribution" Foreground="Black" FontSize="9" FontWeight="Bold" TextWrapping="Wrap" HorizontalAlignment="Right" Margin="10, 0, 10, 0" DockPanel.Dock="Top" Text="{Binding Attribution, UpdateSourceTrigger=PropertyChanged}"/>
.
.
.
CardLayout类-由控件模板填充数据。我使用label,因为它似乎是最简单的控件,因为我无论如何都要替换它的逻辑树:

<Label x:Class="Cards.CardLayout"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Style="{StaticResource testLabel}">
</Label>
CardWindow类-将CardLayout作为子级保存-其目的是最终拥有不同的窗口,其中保存不同数量的CardLayout

<Window x:Class="Cards.CardWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Grid Name="gridCard">

    </Grid>
</Window>
所以,当它运行时,我希望有一个窗口包含一个网格,其中包含一个标签,该标签的逻辑树已被ControlTemplate替换,并通过动态绑定填充


很抱歉问了这么一个漫无边际的问题,我不知道我是否以错误的方式做了正确的事情,或者我应该放弃这一切,以不同的方式来处理它。

在等待答案的过程中,我简化了一切,从硬连接的值开始,然后逐渐添加一个步骤,直到它起作用。现在我已经把它全部充实了,我看不出我在做什么不同

为了完整起见,这里是我简化的ControlTemplate,它与问题中的代码一起工作:

<Application.Resources>
    <Style TargetType="{x:Type Label}" x:Key="testWindow4">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Label}">
                    <Grid>
                        <TextBlock Text="{Binding CardName}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Application.Resources>


其中CardName是CardDetails中的字符串属性。

我建议将CardLayout实现为用户控件。这将更容易编辑。
<Window x:Class="Cards.CardWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Grid Name="gridCard">

    </Grid>
</Window>
public partial class CardWindow : Window
{
    public CardWindow()
    {
        InitializeComponent();
    }

    public CardWindow(CardLayout dataIn)
    {
        InitializeComponent();
        Initialise(dataIn);
    }

    public void Initialise(CardLayout dataIn)
    {
        gridCard.Children.Add(dataIn);
    }
}
<Application.Resources>
    <Style TargetType="{x:Type Label}" x:Key="testWindow4">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Label}">
                    <Grid>
                        <TextBlock Text="{Binding CardName}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Application.Resources>