【问题标题】:How to create a rounded gradient in WPF [closed]如何在 WPF 中创建圆角渐变 [关闭]
【发布时间】:2019-07-01 10:43:19
【问题描述】:

我正在尝试实现这种非线性渐变:

我的问题:我只能创建从顶部到中心/底部到中心或从左到中心/从右到中心的渐变,但它应该有某种圆形渐变或其他东西。我需要和上图一样。

目前我正在对进度条和其中的动画使用线性渐变,但这不是我需要的。

                <Border BorderThickness="1"
                        BorderBrush="#33B8F0"
                        Padding="2"
                        Background="#2F2865"
                        CornerRadius="2">
                    <ProgressBar IsIndeterminate="True"
                                 MinHeight="40"
                                 BorderThickness="0">
                        <ProgressBar.Background>
                            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                <GradientStop Color="#206fb6" Offset="0.0" />
                                <GradientStop Color="#39437d" Offset="0.2" />
                                <GradientStop Color="#39437d" Offset="0.8" />
                                <GradientStop Color="#206fb6" Offset="1.0" />
                            </LinearGradientBrush>
                        </ProgressBar.Background>
                        <ProgressBar.Foreground>
                            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                <GradientStop Color="#38e2ff" Offset="0.0" />
                                <GradientStop Color="#78c4fe" Offset="0.1" />
                                <GradientStop Color="#78c4fe" Offset="0.89" />
                                <GradientStop Color="#38e2ff" Offset="1.0" />
                            </LinearGradientBrush>
                        </ProgressBar.Foreground>
                    </ProgressBar>
                </Border>

它看起来像这样。

【问题讨论】:

  • 不知道你为什么被搁置我认为你的问题很清楚
  • @DenisSchaf 可能是因为发帖人没有解释什么想要的结果是什么,或者他不只是交换渐变?您的答案假设渐变需要四舍五入。这是 OP 真正想要的吗?
  • 好吧,我想你可以这样看
  • @DenisSchaf 喜欢 什么?这就是这个问题被关闭的原因。其中一张接近投票来自在 WPF 上拥有金色徽章的人。显然,这个问题需要澄清。您的回答比问题本身更能澄清问题
  • 我从来没有说你错了,我只是个人不同意。但我认为不分享同样的想法是完全可以的

标签: c# wpf gradient


【解决方案1】:

这种方法有点不寻常,但我认为它可以为您解决问题。您可以通过模糊边界来获得您正在寻找的外观。请注意,下面的代码更像是伪 XAML,您需要根据自己的需要进行调整

            <Grid Height="20" Width="200">
                <Grid>
                    <Border BorderBrush="#241C59" BorderThickness="1" CornerRadius="1" Background="#2D255B">
                        <Border BorderBrush="#206fb6" BorderThickness="4" CornerRadius="2" ClipToBounds="True" Margin="-1">
                            <Border.Effect>
                                <BlurEffect Radius="10"/>
                            </Border.Effect>
                        </Border>
                    </Border>
                    <Border Margin="1" VerticalAlignment="Stretch" BorderThickness="0." Background="#69ABDB" HorizontalAlignment="Left" Width="50">
                        <Border BorderBrush="#38e2ff" BorderThickness="2" CornerRadius="2" ClipToBounds="False">
                            <Border.Effect>
                                <BlurEffect Radius="5"/>
                            </Border.Effect>
                        </Border>
                    </Border>
                </Grid>
            </Grid>

您的要求:

结果:

您可能需要稍微修改颜色以使其完全匹配,但一般来说这会为您做到

可以使用这样的视觉画笔将控件应用为背景:

<ProgressBar>
    <ProgressBar.Background>
        <VisualBrush>
            <VisualBrush.Visual>
                <Border BorderBrush="HotPink">
                </Border>
            </VisualBrush.Visual>
        </VisualBrush>
    </ProgressBar.Background>
</ProgressBar>

使用自定义控件模板甚至更好

编辑: 正如您要求的更详细的版本,它将向您展示如何使用带有自定义控件模板的 prograssbar 通常,您必须使用转换器来缩放内部条以匹配百分比。但是我很懒,在这里给了你一个解决方案,只有在进度条大约 100 px 宽的情况下才有效,但是你应该很容易弄清楚如何使用转换器,这样你就可以从中删除宽度定义并添加一个尺寸转换器。不能在这里为你做所有的工作:P

            <ProgressBar Value="40" Height="20" Width="100">
                <ProgressBar.Style>
                    <Style TargetType="ProgressBar">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="ProgressBar">
                                    <Viewbox Stretch="Fill">                                            
                                      <Grid Height="{TemplateBinding Height}" Width="102">
                                        <Grid>
                                            <Border BorderBrush="#241C59" BorderThickness="1" CornerRadius="1" Background="#2D255B">
                                                <Border BorderBrush="#206fb6" BorderThickness="4" CornerRadius="2" ClipToBounds="True" Margin="-1">
                                                    <Border.Effect>
                                                        <BlurEffect Radius="10"/>
                                                    </Border.Effect>
                                                </Border>
                                            </Border>
                                            <Border Margin="1" VerticalAlignment="Stretch" Background="#69ABDB" HorizontalAlignment="Left" Width="{TemplateBinding Value}">
                                                <Border BorderBrush="#38e2ff" BorderThickness="2" CornerRadius="2" ClipToBounds="False">
                                                    <Border.Effect>
                                                        <BlurEffect Radius="5"/>
                                                    </Border.Effect>
                                                </Border>
                                            </Border>
                                        </Grid>
                                    </Grid>
                                    </Viewbox>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </ProgressBar.Style>
            </ProgressBar>

编辑 2:

为了使它更通用一点,我们需要找到一种方法将一个控件的宽度设置为一个相对值。然而,WPF 无法做到这一点,这就是为什么我们需要转换器来实现这一点。这个例子展示了如何使这个进度条变得更加通用:

 <!--This needs to go into your window resources-->
 <local:NumberToLeftRelativeWidth x:Key="numberToLeftRelativeWidth" />
 <local:NumberToRightRelativeWidth x:Key="numberToRightRelativeWidth" />


 <!--This is the control-->
 <ProgressBar Height="30" Value="80">
                                        <ProgressBar.Style>
                                            <Style TargetType="ProgressBar">
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="ProgressBar">
                                                                <Grid Height="{TemplateBinding Height}">
                                                                    <Grid.ColumnDefinitions>
                                                                    <ColumnDefinition Width="{TemplateBinding Value, Converter={StaticResource numberToLeftRelativeWidth}, ConverterParameter={TemplateBinding Maximum}}"/>
                                                                    <ColumnDefinition Width="{TemplateBinding Value, Converter={StaticResource numberToRightRelativeWidth}, ConverterParameter={TemplateBinding Maximum}}"/>
                                                                </Grid.ColumnDefinitions>
                                                                        <Border Grid.ColumnSpan="2" BorderBrush="#241C59" BorderThickness="1" CornerRadius="1" Background="#2D255B">
                                                                            <Border BorderBrush="#206fb6" BorderThickness="4" CornerRadius="2" ClipToBounds="True" Margin="-1">
                                                                                <Border.Effect>
                                                                                    <BlurEffect Radius="10"/>
                                                                                </Border.Effect>
                                                                            </Border>
                                                                        </Border>
                                                                    <Border Grid.Column="0" Margin="1" VerticalAlignment="Stretch" Background="#69ABDB">
                                                                            <Border BorderBrush="#38e2ff" BorderThickness="2" CornerRadius="2" ClipToBounds="False">
                                                                                <Border.Effect>
                                                                                    <BlurEffect Radius="5"/>
                                                                                </Border.Effect>
                                                                            </Border>
                                                                        </Border>
                                                                </Grid>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
                                        </ProgressBar.Style>
                                    </ProgressBar>

您将需要两个转换器:

    public class NumberToLeftRelativeWidth : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        try
        {
            int width = System.Convert.ToInt32(value);
            int maximum = 100;
            return (new GridLength(width, GridUnitType.Star));
        }
        catch (Exception)
        {
            return false;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

    public class NumberToRightRelativeWidth : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            try
            {
                int width = System.Convert.ToInt32(value);
                int maximum = 100;
                return (new GridLength((double)(maximum - width), GridUnitType.Star));
            }
            catch (Exception)
            {
                return false;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

虽然这可行,但这不是一个理想的解决方案,因为这仅在进度条的最大值为 100 时才有效。大多数情况下都是这种情况,但是如果最大值为 != 100,则转换器中的最大变量需要为调整。我愿意接受有关如何改进的建议

【讨论】:

  • 抱歉,我这边看起来不太好。
  • 你能详细说明一下吗? xaml 应该在每台机器上呈现相同的内容,因此它应该看起来就像上面的图片一样,与您开始使用的图像非常相似。唯一可能影响结果的可能是应用于 XAML 中某处的边界控件的样式
  • 丹尼斯,您能否提供完整示例如何在 ProgressBar 中使用您的答案,抱歉不清楚我只是没有足够的 WPF 经验。
  • @JoanVenge 编辑 2 以下的所有内容都适合您
  • 非常感谢丹尼斯,它对我帮助很大!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
  • 2011-10-08
  • 2021-12-28
相关资源
最近更新 更多