Я немного искал в Интернете и StackOverflow. Зачем мне это нужно: у меня есть два UserControl
с именами PlusButton
и MinusButton
, и они имеют как общий XAML, так и общий программный код. Я хочу использовать общий базовый класс, который в идеале также должен иметь XAML и код-позади.
Я видел опубликованный ответ здесь , но у меня недостаточно опыта в XAML, чтобы применить это решение. Я был бы счастлив со ссылкой на официальную страницу документации, которая узнает мне, что мне нужно для этого сделать. Я привык к программному обеспечению, так как я также использую WinForms, поэтому я не против, если мне придется делать программный код.
Я понимаю, что код позади гораздо легче, чем XAML, поэтому у меня много кода, который, вероятно, был бы лучше реализован в XAML.
Если я использую решение, опубликованное здесь Я получаю ошибки компилятора:
cs_wpf_test_1.ArrowButton
не может быть корнем файла XAML, поскольку он был определен с использованием XAML. Строка 1, позиция 20.
- Предупреждение CS0108
PlusButton.InitializeComponent()
скрывает унаследованный элемент ArrowButton.InitializeComponent()
. Используйте новое ключевое слово, если было скрыто.
Я получаю две ошибки компилятора, перечисленные выше, и я не знаю, как наиболее правильно обойти эти ошибки. Я хотел бы, чтобы это было легко обслуживать.
Приведенный ниже код является версией моего кода до того, как у меня были эти ошибки компилятора.
PlusButton.xaml
<UserControl x:Class="cs_wpf_test_1.PlusButton"
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"
xmlns:local="clr-namespace:cs_wpf_test_1"
mc:Ignorable="d"
d:DesignHeight="120" d:DesignWidth="175"
Loaded="UserControl_Loaded">
<Button Name="MyButton" Focusable="False" Padding="0,0,0,0">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates" CurrentStateChanged="CommonStates_CurrentStateChanged">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Pressed" />
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Name="MyCanvas">
<Polyline Stroke="Blue" Name="MyPolyline">
<Polyline.Points>
<PointCollection>
<Point X="5" Y="95" />
<Point X="95" Y="95" />
<Point X="50" Y="5" />
<Point X="5" Y="95" />
</PointCollection>
</Polyline.Points>
</Polyline>
</Canvas>
<Canvas HorizontalAlignment="Center" VerticalAlignment="Center"
Width="100" Height="100" Name="MySecondCanvas">
<Line Stroke="Black" X1="50" Y1="10"
X2="50" Y2="90"
Name="MySignLine1" StrokeThickness="4"/>
<Line Stroke="Black" X1="10" Y1="50"
X2="90" Y2="50"
Name="MySignLine2" StrokeThickness="4"/>
</Canvas>
</Grid>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</UserControl>
PlusButton.xaml.cs
public partial class PlusButton : UserControl
{
internal Polyline MyTemplatePolyline;
internal Line MyTemplateSignLine1, MyTemplateSignLine2;
internal Canvas MyTemplateCanvas,
MyTemplateSecondCanvas;
public PlusButton()
{
InitializeComponent();
MyButton.Margin = new Thickness(
-MyButton.BorderThickness.Left,
-MyButton.BorderThickness.Top,
-MyButton.BorderThickness.Right,
-MyButton.BorderThickness.Bottom);
}
internal void SetPseudofocused(bool p)
{
if (p)
{
BorderBrush = Brushes.Blue;
}
else
{
BorderBrush = Brushes.Transparent;
}
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
MyButton.ApplyTemplate();
MyTemplatePolyline = (Polyline)MyButton.Template.FindName("MyPolyline", MyButton);
MyTemplateSignLine1 = (Line)MyButton.Template.FindName("MySignLine1", MyButton);
MyTemplateSignLine2 = (Line)MyButton.Template.FindName("MySignLine2", MyButton);
MyTemplateCanvas = (Canvas)MyButton.Template.FindName("MyCanvas", MyButton);
MyTemplateSecondCanvas = (Canvas)MyButton.Template.FindName("MySecondCanvas", MyButton);
UpdateMyLayout();
}
private void CommonStates_CurrentStateChanged(object sender, VisualStateChangedEventArgs e)
{
var btn = e.Control as Button;
if (e.NewState.Name == "MouseOver")
{
btn.Background = Brushes.White;
}
else if (e.NewState.Name == "Pressed")
{
btn.Background = Brushes.LightBlue;
}
else if (e.NewState.Name == "Disabled")
{
btn.Background = Brushes.Gray;
}
else
{
btn.Background = (Brush)MyButton.FindResource(SystemColors.ControlBrushKey);
}
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == WidthProperty || e.Property == HeightProperty || e.Property == BorderThicknessProperty)
{
UpdateMyLayout();
}
}
internal void UpdateMyLayout()
{
if (MyTemplateCanvas == null)
{
return;
}
MyTemplateCanvas.Height = Height;
MyTemplateCanvas.Width = Width;
double h = ActualHeight - BorderThickness.Top -
BorderThickness.Bottom;
double w = ActualWidth - BorderThickness.Left -
BorderThickness.Right;
MyTemplatePolyline.Points.Clear();
MyTemplatePolyline.Points.Add(new Point(5, h - 5));
MyTemplatePolyline.Points.Add(new Point(w - 5, h - 5));
MyTemplatePolyline.Points.Add(new Point(w / 2, 5));
MyTemplatePolyline.Points.Add(new Point(5, h - 5));
h = MyTemplateSecondCanvas.ActualHeight;
w = MyTemplateSecondCanvas.ActualWidth;
double ltrbPadding = h / 3;
double l1 = h - 2 * ltrbPadding;
double l2 = w - 2 * ltrbPadding;
double l = Math.Min(l1, l2);
// draw a cross with two lines:
MyTemplateSignLine1.X1 = l / 2d + ltrbPadding;
MyTemplateSignLine1.X2 = l / 2d + ltrbPadding;
MyTemplateSignLine1.Y1 = ltrbPadding;
MyTemplateSignLine1.Y2 = l + ltrbPadding;
MyTemplateSignLine2.X1 = ltrbPadding;
MyTemplateSignLine2.X2 = l + ltrbPadding;
MyTemplateSignLine2.Y1 = ltrbPadding + l / 2d;
MyTemplateSignLine2.Y2 = ltrbPadding + l / 2d;
// update focus border size:
double v = ActualHeight / 25d;
BorderThickness = new Thickness(v, v, v, v);
}
}
MinusButton.xaml
То же, что и первый файл XAML, но XAML MySecondCanvas
содержит только один Line
.
MinusButton.xaml.cs
То же, что и первый .cs
файл, но:
- Он не создает и не использует
MyTemplateSignLine1
и MyTemplateSignLine2
, он просто использует MyTemplateSignLine
.
MyTemplatePolyline
содержит другие точки, похожие на стрелку вниз (первая стрелка, перевернутая вверх ногами).
MyTemplateSignLine
аналогично MyTemplateSignLine2
из другого файла XAML и кода с выделенным кодом.