Начиная с Java, я действительно привык к обычной практике, когда речь заходит о создании компонентов GUI: обычно я делаю какой-то базовый класс, который содержит все общие объекты для моих компонентов графического интерфейса, а затем я расширяю его.
Итак, в основном, это то, что я хотел бы достичь с помощью С# и 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
.
Это позволит мне обмениваться компонентами между различными производными классами без необходимости писать код каждый раз, когда он мне нужен.
Например, если я хочу, чтобы все мои компоненты имели эту закругленную границу, я хотел бы просто поместить ее в класс басов, а затем использовать ее во всех производных, не переписывая ее.
Конечно, каждый класс С# имеет свой собственный метод InitializeComponent()
, и это, вероятно, означает, что производный компонент будет создавать свой собственный контент, удалив базовый класс "один".
Удаление метода из конструктора DerivedClass
дает базовое содержимое даже в производном классе, но, конечно, я теряю все, что я сделал в окне дизайна XAML DerivedClass
.
Вызов базового конструктора из DerivedClass
не имеет никакого эффекта, так как он вызывается перед производным InitializeComponent()
.
Итак, возникает вопрос: как я могу использовать дизайн XAML из базового класса в производный, не нарушая конструкцию XAML производного класса? Есть ли способ просто добавить контент в базовый класс при работе с самим дизайнером?
(Я знаю, что я могу удалить XAML для производного класса и делать то, что хочу делать по коду, но я хочу знать, могу ли я сделать это только с дизайнером, поскольку я не хочу писать свой графический интерфейс когда у меня есть дизайнер)
EDIT:
После ответа 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
, поскольку мне нужно, чтобы у него были некоторые общие свойства/методы по другим причинам.
Что вы думаете о моем решении? Имеет ли смысл?