WPF произвольный пограничный контроль - PullRequest
2 голосов
/ 31 августа 2009

Мне нужно разработать элемент управления wpf, который будет вести себя так же, как хорошо известная граница. Форма контроля должна быть новой частью. Каждый определяемый замкнутый путь должен использоваться для определения внешнего вида элемента управления.

Мне нужна помощь для достижения этой цели. В настоящее время я не знаю, как поменять прямоугольник (??) с замкнутым путем.

Любая помощь будет принята с благодарностью.

1 Ответ

6 голосов
/ 31 августа 2009

Редактировать Здесь идет прямой ответ на ваш вопрос. Мы напишем производный класс 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 == половина доступной ширины / высоты и т. Д.

Надеюсь, это поможет.

...