WPF自由​​格式边框控制 [英] WPF freeform border control

查看:66
本文介绍了WPF自由​​格式边框控制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须开发一个wpf控件,该控件应具有与众所周知的边界相同的行为. 控件的形状应为新的部分.每个可定义的闭合路径均应用于定义控件的外观.

我需要帮助来实现这一目标. 目前,我不知道如何将矩形(??)与闭合路径互换.

任何帮助将不胜感激.

解决方案

编辑这里是您问题的直接答案.我们将编写一个ContentControl派生类,它具有非常灵活的border形式.此想法的依据位于 OpacityMask 中.

如果您想进一步了解这种方法,请查看

Themes \ 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 UI:

<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的具体像素值.网格使这一技巧成为可能.因此,将其视为百分比. IE. 1 ==全宽或全高. 0.5 ==可用宽度/高度的一半,依此类推.

希望这会有所帮助.

i have to develop a wpf control which shall have the same behaviour as the well known border. The shape of the control shall be the new part. Every definable closed path shall be used to define the appearence of the control.

I need help to achieve this. Currently i have no idea how to interchange the rectangle(??) with the closed path.

Any help would be highly appreciated.

解决方案

Edit Here goes direct answer to your question. We will write a ContentControl derived class, with very flexible form of border. Basis for this idea lies in OpacityMask.

If you would like to know more about this approach take a look on example from Chris Cavanagh's solution for rounded corners.

Step 1. Create custom control 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))
        );
    }
  }
}

Themes\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>

More reading on custom controls can be found on CodeProject.

Step 2. Usage. Now you can place any content inside this control. Its default shape is rectangle. So the following code will result in regular StackPanel UI:

<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>

But if you define custom FormGeometry you'll get custom shape. For example, the following form geometry presents inner controls inside a diamond:

<cc:FreeFormContentControl FormGeometry="M0,0.5 L0.5,0 1,0.5 0.5,1z">

To read more about geometry definition from XAML, read corresponding section on MSDN: Path Markup Syntax.

The last thing to mention here, is that you don't have to specify or calculate concrete pixel values of your FormGeomtry. Grid makes this trick possible. So think of it as of percentage. I.e. 1 == full width or height. 0.5 == half of available width/hight and so on.

Hope this helps.

这篇关于WPF自由​​格式边框控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆