Редактировать Здесь идет прямой ответ на ваш вопрос. Мы напишем производный класс ContentControl с очень гибкой формой границы. Основа для этой идеи лежит в OpacityMask .
Если вы хотите узнать больше об этом подходе, взгляните на пример из решения Криса Кавана для закругленных углов.
Шаг 1 . Создать пользовательский элемент управления FreeFormContentControl:
FreeFormContentControl.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfApplication5
{
public class FreeFormContentControl : ContentControl
{
public Geometry FormGeometry
{
get { return (Geometry)GetValue(FormGeometryProperty); }
set { SetValue(FormGeometryProperty, value); }
}
public static readonly DependencyProperty FormGeometryProperty =
DependencyProperty.Register("FormGeometry", typeof(Geometry), typeof(FreeFormContentControl), new UIPropertyMetadata(null));
static FreeFormContentControl()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(FreeFormContentControl),
new FrameworkPropertyMetadata(typeof(FreeFormContentControl))
);
}
}
}
Темы \ Generic.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication5">
<Style TargetType="{x:Type local:FreeFormContentControl}">
<Setter Property="FormGeometry"
Value="M0,0 L1,0 1,1 0,1z" />
<Setter Property="Background"
Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:FreeFormContentControl}">
<Grid>
<Path Name="mask"
Data="{TemplateBinding FormGeometry}"
Fill="{TemplateBinding Background}" />
<Grid>
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}" />
</Grid.OpacityMask>
<ContentPresenter />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Дополнительные сведения о пользовательских элементах управления можно найти в CodeProject .
Шаг 2 . Использование. Теперь вы можете разместить любой контент внутри этого элемента управления. Его формой по умолчанию является прямоугольник. Поэтому следующий код приведет к обычному пользовательскому интерфейсу StackPanel:
<Window x:Class="WpfApplication5.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:WpfApplication5"
Title="Window1"
Height="300"
Width="300">
<Grid>
<cc:FreeFormContentControl>
<StackPanel>
<Button Content="Any" />
<Button Content="Content" />
<TextBlock Text="Goes" />
<TextBox Text="Here" />
</StackPanel>
</cc:FreeFormContentControl>
</Grid>
</Window>
Но если вы определите пользовательскую форму FormGeometry, вы получите пользовательскую форму. Например, следующая геометрия формы представляет внутренние элементы управления внутри ромба:
<cc:FreeFormContentControl FormGeometry="M0,0.5 L0.5,0 1,0.5 0.5,1z">
Чтобы узнать больше об определении геометрии из XAML, прочитайте соответствующий раздел в MSDN: Синтаксис разметки пути .
Последнее, что следует упомянуть здесь, это то, что вам не нужно указывать или вычислять конкретные значения пикселей вашей FormGeomtry. Сетка делает этот трюк возможным. Так что думайте об этом как о процентах. То есть 1 == полная ширина или высота. 0,5 == половина доступной ширины / высоты и т. Д.
Надеюсь, это поможет.