【问题标题】:How to make transparent part on non-transparent user control in WPF如何在 WPF 中的非透明用户控件上制作透明部分
【发布时间】:2017-12-13 09:20:51
【问题描述】:

在我的 MainWindow.xaml 中有用户控件图块,每个图块的背景设置如下:

ucTile.Background = new SolidColorBrush(Colors.Some);

取决于各种用户设置。

现在我想为我的应用添加一个新功能:为主窗口设置自定义背景图像的可能性

但是我需要我的瓷砖的某些部分是透明的,以显示它们下方的图像。像这样:

这就是我的瓷砖现在的样子:

如何做到这一点?我不能将我的 ucTile 背景设置为透明,因为如果应该保持着色。 是否有一些组件 inf WPF 会充当“洞”,显示非透明元素下的内容?

【问题讨论】:

  • 您可以将 PNG 设置为背景图像。 PNG 支持透明度。
  • “我的瓷砖的一部分......透明”究竟是如何定义的?或许可以添加一张图片来展示您想要实现的目标。
  • @Clemens 我添加了图片,希望现在清楚了。
  • 这看起来像一条带有描边和填充以及适当几何图形的路径。该控件中是否还有其他内容,例如一些文字?
  • 对不起,我不会下载那个。在此处发布图片。

标签: wpf xaml transparency


【解决方案1】:

简单的解决方案:

<Window Background="Transparent">
    <Polygon Fill="LightBlue"/>
</Window>

您需要添加Points 以获得所需的形状!

阅读更多关于多边形here!

这里有一些细节,因为 some1 觉得无缘无故投反对票是件好事......

用户控制

<UserControl x:Class="WpfApp1.FolderControl"
         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:WpfApp1"
         mc:Ignorable="d">
<Grid Margin="10">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Polygon Fill="Red"
             Grid.RowSpan="2"
             Points="0,0 , 50,0 , 55,10 , 100,10 , 100,80 , 0,80 " />
    <Image Source="if_desktop_83651.png" Margin="5,20,5,5" Height="24" Width="24"></Image>
    <Border Background="Green"
            Grid.Row="1"
            Margin="5">
        <TextBlock Text="Caption" 
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"
                   Foreground="White"/>
    </Border>
</Grid>

窗口

<Window x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp1"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525"
    Background="Green">
<local:FolderControl HorizontalAlignment="Center"
                     VerticalAlignment="Center"/>

结果

优点:

  • 你可以做任何你想要的形状

缺点:

  • 不会调整大小 -> 在代码中计算 Points

【讨论】:

  • 感谢您提供好的解决方案,@Felix D。在这种情况下,多边形对我来说真的很好。
  • @Gabriel 很高兴它有帮助!
【解决方案2】:

您可以在其 ControlTemplate 中为 UserControl 的轮廓添加一个 Path 元素。 Path 的FillStrokeStrokeThickness 属性绑定到UserControl 的BackgroundBorderBrush 和(新定义的)OutlineThickness,因此您可以照常设置。

<UserControl x:Class="YourNamespace.Tile" ...>
    <UserControl.Template>
        <ControlTemplate TargetType="local:Tile">
            <Grid>
                <Path Fill="{TemplateBinding Background}"
                      Stroke="{TemplateBinding BorderBrush}"
                      StrokeLineJoin="Round"
                      StrokeThickness="{TemplateBinding OutlineThickness}"
                      Data="{TemplateBinding Outline}"/>

                <ContentPresenter
                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </Grid>
        </ControlTemplate>
    </UserControl.Template>
    <Grid>
        ...
    </Grid>
</UserControl>

Path 绑定到 Tile 控件的两个依赖属性:

public partial class Tile : UserControl
{
    public Tile()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty OutlineProperty =
        DependencyProperty.Register(
            nameof(Outline), typeof(Geometry), typeof(Tile));

    public Geometry Outline
    {
        get { return (Geometry)GetValue(OutlineProperty); }
        set { SetValue(OutlineProperty, value); }
    }

    public static readonly DependencyProperty OutlineThicknessProperty =
        DependencyProperty.Register(
            nameof(OutlineThickness), typeof(double), typeof(Tile), 
            new PropertyMetadata(1.0, (o, e) => ((Tile)o).UpdateOutline()));

    public double OutlineThickness
    {
        get { return (double)GetValue(OutlineThicknessProperty); }
        set { SetValue(OutlineThicknessProperty, value); }
    }

    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
    {
        base.OnRenderSizeChanged(sizeInfo);
        UpdateOutline();
    }

    private void UpdateOutline()
    {
        var geometry = new StreamGeometry();
        var size = RenderSize;
        var border = OutlineThickness / 2d;

        using (var sgc = geometry.Open())
        {
            sgc.BeginFigure(new Point(border, border), true, true);
            sgc.LineTo(new Point(size.Width - 20, border), true, true);
            sgc.LineTo(new Point(size.Width - border, 20), true, true);
            sgc.LineTo(new Point(size.Width - border, size.Height - border), true, true);
            sgc.LineTo(new Point(0, size.Height - border), true, true);
        }

        Outline = geometry;
    }
}

现在根据需要扩展UpdateOutline 方法。


如果 XAML 设计者抱怨 ControlTemplate 的 TargetType,你也可以使用这个:

<UserControl.Template>
    <ControlTemplate TargetType="UserControl">
        <Grid>
            <Path Fill="{TemplateBinding Background}"
                  Stroke="{TemplateBinding BorderBrush}"
                  StrokeLineJoin="Round"
                  StrokeThickness="{Binding OutlineThickness, RelativeSource={RelativeSource TemplatedParent}}"
                  Data="{Binding Outline, RelativeSource={RelativeSource TemplatedParent}}"/>

            <ContentPresenter
                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </ControlTemplate>
</UserControl.Template>

【讨论】:

    猜你喜欢
    • 2016-02-15
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多