【发布时间】:2013-09-03 23:34:48
【问题描述】:
来自 Java,在制作 GUI 组件时我真的习惯了一种常见的做法:我通常会做某种基类,其中包含我的 GUI 组件的所有常见对象,然后我扩展它。
所以,基本上,这就是我想用 C# 和 XAML 实现的目标。
为了让问题更清楚,这里有一个我正在做的例子(这是行不通的!):
我们有一个带有自己的 XAML 的基类
<UserControl x:Class="BaseClass"
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"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
<Border BorderBrush="Aqua" BorderThickness="10" CornerRadius="10" x:Name="Border" HorizontalAlignment="Left" Height="480" VerticalAlignment="Top" Width="480"/>
</Grid>
</UserControl>
然后我们有了一个扩展第一个类的类
<base:BaseClass x:Class="DerivedClass"
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:base="clr-namespace:BaseClass"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="60" d:DesignWidth="200">
<Grid x:Name="LayoutRoot" Margin="0" Width="200" Height="60" MaxWidth="200" MaxHeight="60" Background="{StaticResource PhoneAccentBrush}">
<TextBlock x:Name="dummyText" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Dummy Plugin" VerticalAlignment="Top" Height="40" Width="180" Foreground="White" TextAlignment="Center"/>
</Grid>
</base:BaseClass>
从 2 个 XAML 代码开始,我想做的是将 DerivedClass 放入 BaseClass 容器中。
这将允许我在各个派生类之间共享组件,而无需每次需要时都编写代码。
例如,如果我希望我的所有组件都具有圆形边框,我想将它放在低音类中,然后将它放在所有派生类中,而无需重写它。
当然,每个 c# 类都有自己的 InitializeComponent() 方法,这可能意味着派生组件将通过删除基类的内容来构建自己的内容。
从DerivedClass 构造函数中删除该方法为我提供了即使在派生类中的基本内容,但是,当然,我丢失了我在DerivedClass 的XAML 设计窗口中所做的一切。
从DerivedClass 调用基本构造函数没有任何效果,因为它在派生的InitializeComponent() 之前调用。
所以问题是:如何在不破坏派生类的 XAML 设计的情况下将 XAML 设计从基类应用到派生类?有什么方法可以简单地将内容添加到基类,同时仍然与设计器本身合作?
(我知道我可以删除派生类的 XAML 并通过代码执行我想要执行的操作,但我想知道我是否可以仅通过设计器执行此操作,因为我不想编写我的 GUI当我有可用的设计师时)
编辑:
根据 HighCore 的回复,我做了一些适用于 Windows Phone 的操作,但我不确定我做的是否正确(是的,它有效,但可能只是错误!)。
这就是我所做的:
BaseControl.xaml
<UserControl x:Class="TestInheritance.BaseControl"
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"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
<TextBlock HorizontalAlignment="Center">BASE</TextBlock>
<ContentPresenter Name="Presenter" Content="{Binding PresenterContent}"/>
</Grid>
</UserControl>
BaseControl.xaml.cs
namespace TestInheritance
{
public partial class BaseControl : UserControl
{
public Grid PresenterContent { get; set; }
public BaseControl()
{
DataContext = this;
InitializeComponent();
}
}
}
DerivedControl.xaml
<local:BaseControl x:Class="TestInheritance.DerivedControl"
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:TestInheritance"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<local:BaseControl.PresenterContent>
<Grid>
<TextBlock VerticalAlignment="Bottom" HorizontalAlignment="Center">DERIVED</TextBlock>
</Grid>
</local:BaseControl.PresenterContent>
</local:BaseControl>
请注意DerivedClass 是BaseClass 的一个实例,因为出于其他原因我需要它们具有一些通用属性/方法。
您对我的解决方案有何看法?有意义吗?
【问题讨论】:
-
是的,基本上这是我所描述的更“自制”的版本。我想这是可以接受的,因为 WPF 和 Windows Phone 之间的 XAML 实现存在差异。
-
嗨@StepTNT 如果我输入您的解决方案并亲自尝试,我会收到错误消息:“WpfApplication18.BaseControl”不能是 XAML 文件的根,因为它是使用 XAML 定义的。第 1 行位置 20。我做错了什么?
-
你应该打开一个新问题并添加一些代码,复制和粘贴并不总是有效:)
-
在 Silverlight(和 Windows Phone)上,也可能在 WinRT(以及通用应用程序)上,您可以扩展 UserControls,它们应该在 Visual Studio 设计器中工作。从我所看到的情况来看,WPF 并非如此。 Visual Studio 中 WPF 的 XAML 设计器(尚)不支持此功能。
-
对于带有可视继承的 WPF 解决方法,请参阅:svetoslavsavov.blogspot.gr/2009/09/… 或对于在祖先中显式定义 GUI,请参阅 support.microsoft.com/kb/957231
标签: c# wpf xaml inheritance windows-phone-8