Я новичок в WPF и хотел создать базовый UserControl, который можно было бы использовать повторно.
Например, у меня есть UserControl: TestBase.
<UserControl x:Class = "UserControls.TestBase"
xmlns = ""
xmlns:x = ""
xmlns:mc = ""
xmlns:d = ""
xmlns:local = "clr-namespace:UserControls"
mc:Ignorable = "d"
Style = "{StaticResource TestBaseDefault}"
d:DesignHeight = "150" d:DesignWidth = "150">
<UserControl.Template>
<ControlTemplate>
<Grid>
<TextBlock Text = "Base Text"
HorizontalAlignment = "Center" VerticalAlignment = "Center"
Foreground = "White"/>
</Grid>
</ControlTemplate>
</UserControl.Template>
</UserControl>
UserControl TestBase использует этот стиль (TestBaseDefault):
<Style x:Key = "TestBaseDefault" TargetType = "{x:Type UserControl}">
<Setter Property = "Margin" Value = "5"/>
<Setter Property = "VerticalAlignment" Value = "Top"/>
<Setter Property = "Template">
<Setter.Value>
<ControlTemplate TargetType = "{x:Type UserControl}">
<Border CornerRadius = "10" BorderThickness = "2" BorderBrush = "{StaticResource ForegroundBrush}" Background = "{StaticResource BackgroundBrush}" Padding = "10">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Теперь я хотел создать второй UserControl, выходящий из TestBase.
На данный момент это выглядит так: Test1
<UserControl x:Class = "UserControls.Test1"
xmlns = ""
xmlns:x = ""
xmlns:mc = ""
xmlns:d = ""
xmlns:local = "clr-namespace:UserControls"
x:Name = "self"
mc:Ignorable = "d"
d:DesignHeight = "150" d:DesignWidth = "150">
<Grid>
<TextBlock Text = "Overriden Text"
HorizontalAlignment = "Center" VerticalAlignment = "Center"
Foreground = "White"/>
</Grid>
</UserControl>
Пришлось удалить ссылки из UserControls, иначе я не смог бы опубликовать вопрос.
Что я хочу знать, можно ли расширить Test1 из TestBase вместо UserControl, чтобы я мог получить доступ к свойствам из базы, использовать из нее стиль и переопределить содержимое по умолчанию?
Если нет, то есть ли другой способ добиться этого?





Базовый класс должен быть определен как класс без какого-либо XAML:
public class TestBase : UserControl
{
public TestBase()
{
Style = FindResource("TestBaseDefault") as Style;
}
}
Затем вы можете использовать его как базовый класс для Test1.
Тест1.xaml:
<local:TestBase x:Class = "WpfApp1.Test1"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable = "d"
d:DesignHeight = "450" d:DesignWidth = "800">
<Grid>
<TextBlock Text = "Overriden Text"
HorizontalAlignment = "Center" VerticalAlignment = "Center"
Foreground = "White"/>
</Grid>
</local:TestBase>
Тест1.xaml.cs:
public partial class Test1 : TestBase
{
public Test1()
{
InitializeComponent();
}
}
Вы не можете переопределить шаблон, поэтому шаблон, который вы определили в TestBase.xaml, следует удалить или объединить с шаблоном, который определяет стиль.
Это сработало для меня, отличное решение. Спасибо!
Поскольку в вашем вопросе все связано со стилем (именно с этим элементом управления), вам следует определить стиль базового элемента управления по умолчанию и установить свойство текста (все, что вы хотите). Вам не нужно создавать базовый класс управления C#, если он вам явно не нужен из-за каких-либо требований.
Если вы хотите использовать или переопределить стиль базового элемента управления, просто используйте это при его определении:
BasedOn=TestBaseDefault
Итак, базовый стиль:
<Style x:Key = "TestBaseDefault" TargetType = "{x:Type TextBox}">
<Setter Property = "Margin" Value = "5"/>
<Setter Property = "VerticalAlignment"
Value = "Top"/>
<Setter Property = "Template">
<Setter.Value>
<ControlTemplate TargetType = "{x:Type UserControl}">
<Border CornerRadius = "10" BorderThickness = "2" BorderBrush = "{StaticResource ForegroundBrush}" Background = "{StaticResource BackgroundBrush}" Padding = "10">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
И для второго элемента управления используйте это:
<Style x:Key = "OtherControlStyle" TargetType = "{x:Type TextBox}" BasedOn = "{StaticResource TestBaseDefault}" >
<Setter Property = "Margin" Value = "10"/>
</Style>
Он будет использовать стиль по умолчанию и ваши новые переопределенные значения.
Наконец, установите стиль для элементов управления:
<TextBox Text = "Base Text" HorizontalAlignment = "Center" VerticalAlignment = "Center" Foreground = "White"
Style = "{StaticResource TestBaseDefault}"/>
и второй и все остальные тоже…
<TextBox Text = "Overriden Text" HorizontalAlignment = "Center" VerticalAlignment = "Center"
Foreground = "White"
Style = "{StaticResource OtherControlStyle}"/>
ps: HorizontalAlignment, ВертикальноеАлигмент, Передний план должны быть определены в стилях, а не непосредственно в элементе управления, но, конечно, там тоже разрешено переопределение некоторых свойств, но нет смысла иметь два значения для одного и того же элемента управления в двух местах. И убедитесь, что вы хорошо на них ссылаетесь…
Я бы предложил использовать композицию вместо наследования для повторного использования элементов управления wpf. Вы можете создать элемент управления, который предоставляет свойства зависимостей, включая такие вещи, как «контент», который помещается где-то внутри вашего элемента управления.