当从动态样式设置颜色时,Xamarin Forms LinearGradientBrush of Frame 不起作用

Xamarin Forms LinearGradientBrush of Frame not working when colors are set from Dynamic Style

我正在尝试使用样式创建一个带有线性渐变的框架。如果我对样式中的颜色进行硬编码,则框架会正确显示。如果我尝试将颜色绑定到我的自定义应用程序设置对象中的属性,该样式将不起作用。下面是一个例子:

这里是静态样式。我将其配置为使用来自对象的相同颜色,以确保值没有任何错误。

        <Style x:Key="wlHeaderGradient" TargetType="Frame">
            <Setter Property="BorderColor" Value="Purple" />
            <Setter Property="HasShadow" Value="False" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="HeightRequest" Value="100" />
            <Setter Property="WidthRequest" Value="100"/>
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="Background">
                <LinearGradientBrush EndPoint="0,1">
                    <GradientStop Color="#FF008080" Offset="0.0" />
                    <GradientStop Color="#FFFF6347" Offset="0.5" />
                    <GradientStop Color="#FF008080" Offset="1.0" />
                </LinearGradientBrush>
            </Setter>
        </Style>

这是动态样式

        <Style x:Key="wlHeaderGradient1" TargetType="Frame">
            <Setter Property="BorderColor" Value="Purple" />
            <Setter Property="HasShadow" Value="False" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="HeightRequest" Value="100" />
            <Setter Property="WidthRequest" Value="100"/>
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="Background">
                <LinearGradientBrush EndPoint="0,1">
                    <GradientStop Color="{Binding HostPublicStyleInfo.CheckInHeaderBgColor1.ColorHex}" Offset="0.0" />
                    <GradientStop Color="{Binding HostPublicStyleInfo.CheckInHeaderBgColor2.ColorHex}" Offset="0.5" />
                    <GradientStop Color="{Binding HostPublicStyleInfo.CheckInHeaderBgColor1.ColorHex}" Offset="1.0" />
                </LinearGradientBrush>
            </Setter>
        </Style>

这是我用来测试的 StackLayout:

        <StackLayout Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Start">
            <StackLayout Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Start">
                <Frame x:Name="frmTest" Style="{StaticResource wlHeaderGradient}">
                </Frame>

                <Frame x:Name="frmTest1" Style="{StaticResource wlHeaderGradient1}">
                </Frame>
            </StackLayout>

            <Label x:Name="lblBGColor1" HorizontalOptions="Center" VerticalOptions="Center"/>
            <Label x:Name="lblBGColor2" HorizontalOptions="Center" VerticalOptions="Center"/>
            <Label x:Name="lblSampleWithStyle" Style="{StaticResource wlPublicHeader1}" Text="This is a working style with binding to same object." />
        </StackLayout>

这是代码隐藏页面的代码,我显示了 CheckInHeaderBgColor1 和 CheckInHeaderBgColor2 值。我在 OnAppearing 事件结束时 运行 此代码:

lblBGColor1.Text = App.gvm_AppSettings.HostPublicStyleInfo.CheckInHeaderBgColor1.ColorHex;
lblBGColor2.Text = App.gvm_AppSettings.HostPublicStyleInfo.CheckInHeaderBgColor2.ColorHex;

这是我得到的输出:

我将整个页面绑定到 CodeBehind 中的应用程序设置,如下所示:

this.BindingContext = App.gvm_AppSettings;

注意:我在页面的其他样式中使用此 AppSettings 对象的其他属性(如下所示),它们似乎有效。在屏幕截图中,您可以看到最后一个标签的文本颜色与其下方屏幕的背景颜色相匹配。

样式如下:

       <Style x:Key="wlPublicHeader1" TargetType="Label" >
            <Setter Property="BackgroundColor" Value="Transparent" />
            <Setter Property="Padding" Value="8,4,8,4" />
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="TextColor" Value="{Binding HostPublicStyleInfo.CheckInFormBgColor1.ColorHex}" />
            <Setter Property="FontSize" Value="Small" />
            <Setter Property="FontAttributes" Value="Bold" />
        </Style>

如果有人知道我做错了什么,我将不胜感激。

更新::

根据下面的反馈 - 我创建了一个 属性 我的自定义颜色对象,它返回一个 Xamarin.Forms.Color 对象并尝试绑定到那个 属性。它不起作用。我还尝试在 App.Xaml 文件中使用动态属性,在加载我的自定义颜色对象时修改这些属性的值,但这也不起作用。以下是更新后的样本:

App.Xaml 颜色

<Application.Resources>
    <ResourceDictionary>
        <Color x:Key="grdHeaderBGColor1">White</Color>
        <Color x:Key="grdHeaderBGColor2">Black</Color>

以下是三个更新的测试样式:

       <Style x:Key="wlHeaderGradient" TargetType="Frame">
            <Setter Property="BorderColor" Value="Purple" />
            <Setter Property="HasShadow" Value="False" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="HeightRequest" Value="100" />
            <Setter Property="WidthRequest" Value="100"/>
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="Background">
                <LinearGradientBrush EndPoint="0,1">
                    <GradientStop Color="#FF008080" Offset="0.0" />
                    <GradientStop Color="#FFFF6347" Offset="0.5" />
                    <GradientStop Color="#FF008080" Offset="1.0" />
                </LinearGradientBrush>
            </Setter>
        </Style>

        <Style x:Key="wlHeaderGradient1" TargetType="Frame">
            <Setter Property="BorderColor" Value="Purple" />
            <Setter Property="HasShadow" Value="False" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="HeightRequest" Value="100" />
            <Setter Property="WidthRequest" Value="100"/>
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="Background">
                <LinearGradientBrush EndPoint="0,1">
                    <GradientStop Color="{Binding HostPublicStyleInfo.CheckInHeaderBgColor1.DisplayColor}" Offset="0.0" />
                    <GradientStop Color="{Binding HostPublicStyleInfo.CheckInHeaderBgColor2.DisplayColor}" Offset="0.5" />
                    <GradientStop Color="{Binding HostPublicStyleInfo.CheckInHeaderBgColor1.DisplayColor}" Offset="1.0" />
                </LinearGradientBrush>
            </Setter>
        </Style>

        <Style x:Key="wlHeaderGradient2" TargetType="Frame">
            <Setter Property="BorderColor" Value="Purple" />
            <Setter Property="HasShadow" Value="False" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="HeightRequest" Value="100" />
            <Setter Property="WidthRequest" Value="100"/>
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>

这里是 XAML 生成示例框架,示例 2 使用动态资源。

        <StackLayout Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Start">
            <StackLayout Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Start">
                <Frame x:Name="frmTest" Style="{StaticResource wlHeaderGradient}">
                </Frame>

                <Frame x:Name="frmTest1" Style="{StaticResource wlHeaderGradient1}">
                </Frame>

                <Frame x:Name="frmTest2" Style="{StaticResource wlHeaderGradient2}">
                    <Frame.Background>
                        <LinearGradientBrush EndPoint="0,1">
                            <GradientStop Color="{DynamicResource grdHeaderBGColor1}" Offset="0.0" />
                            <GradientStop Color="{DynamicResource  grdHeaderBGColor2}" Offset="0.5" />
                            <GradientStop Color="{DynamicResource grdHeaderBGColor1}" Offset="1.0" />
                        </LinearGradientBrush>
                    </Frame.Background>
                </Frame>

            </StackLayout>

            <Label x:Name="lblBGColor1" HorizontalOptions="Center" VerticalOptions="Center"/>
            <Label x:Name="lblBGColor2" HorizontalOptions="Center" VerticalOptions="Center"/>
            <Label x:Name="lblSampleWithStyle" Style="{StaticResource wlPublicHeader1}" Text="This is a working style with binding to same object." />
        </StackLayout>

结果如下:

第二个示例 - 绑定到 Xamarin.Forms.Color 对象根本不起作用。第三个示例,尝试使用动态资源永远不会更新为新颜色(它们保持静态黑白值),即使我已确保在加载自定义颜色对象时更改了值。

所以我又在这里不知所措。

根据我的经验,当您尝试像这样将颜色绑定到字符串十六进制值时,我发现颜色绑定不正确。您可以将这些字符串字段的类型更改为颜色对象并尝试。

您的 CheckInHeaderBgColor1 和 CheckInHeaderBgColor2 属性是 Color 类型吗?是的话直接绑定试试

动态颜色也可以。像这样:

       <Style x:Key="wlHeaderGradient" TargetType="Frame">
            <Setter Property="BorderColor" Value="Purple" />
            <Setter Property="HasShadow" Value="False" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="HeightRequest" Value="100" />
            <Setter Property="WidthRequest" Value="100"/>
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="Background">
                <LinearGradientBrush EndPoint="0,1">
                    <GradientStop Color="{DyanmicResource Color1}" Offset="0.0" />
                    <GradientStop Color="{DyanmicResource Color2}" Offset="0.5" />
                    <GradientStop Color="{DyanmicResource Color3}" Offset="1.0" />
                </LinearGradientBrush>
            </Setter>
        </Style>

The second sample - binding to a Xamarin.Forms.Color object does not work at all.

第二个问题是需要设置Path为sub-属性来做绑定

设置页面名称。

x:Name="root"

带绑定的样式:

 <Style x:Key="wlHeaderGradient1"  TargetType="Frame">
          
            <Setter Property="BorderColor" Value="Purple" />
            <Setter Property="HasShadow" Value="False" />
            <Setter Property="CornerRadius" Value="0" />
            <Setter Property="HeightRequest" Value="100" />
            <Setter Property="WidthRequest" Value="100"/>
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="Background">
               
                <LinearGradientBrush EndPoint="0,1">
                    <GradientStop Color="{Binding Path = BindingContext.CheckInHeaderBgColor1 ,Source={x:Reference root}}" Offset="0.0" />
                    <GradientStop Color="{Binding Path = BindingContext.CheckInHeaderBgColor2 ,Source={x:Reference root}}" Offset="0.5" />
                    <GradientStop Color="{Binding Path = BindingContext.CheckInHeaderBgColor1 ,Source={x:Reference root}}" Offset="1.0" />
                </LinearGradientBrush>
            </Setter>
        </Style>

Xaml:

   <StackLayout Orientation="Vertical" HorizontalOptions="Center" VerticalOptions="Start">
        <StackLayout Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Start">


            <Frame Style="{StaticResource wlHeaderGradient1}"  x:Name="frmTest1" >
            </Frame>

        </StackLayout>

    </StackLayout>

后面的代码:

 public Page12()
    {
        InitializeComponent();
        this.BindingContext = new HostPublicStyleInfo();
    }

视图模型:

public class HostPublicStyleInfo
{
    public HostPublicStyleInfo()
    {
        CheckInHeaderBgColor1 = "#FF008080";
        CheckInHeaderBgColor2 = "#FFFF6347";
        frmTest2Style = "frmTest2GradientStyle";
    }
    public string frmTest2Style { get; set; }
    public string CheckInHeaderBgColor1 { get; set; }
    public string CheckInHeaderBgColor2 { get; set; }


}

The third example, attempting to use the dynamic resources never updates to the new colors (they stay the static black and white values) even though I have ensured the values are being changed when the custom color objects are being loaded.

  1. 在样式中而不是在框架中设置白-黑-白。

    <Style x:Key="wlHeaderGradient2" TargetType="Frame">
             <Setter Property="BorderColor" Value="Purple" />
             <Setter Property="HasShadow" Value="False" />
             <Setter Property="CornerRadius" Value="0" />
             <Setter Property="HeightRequest" Value="100" />
             <Setter Property="WidthRequest" Value="100"/>
             <Setter Property="HorizontalOptions" Value="Center" />
             <Setter Property="VerticalOptions" Value="Center" />
             <Setter Property="Background">
                 <LinearGradientBrush EndPoint="0,1">
                     <GradientStop Color="{DynamicResource grdHeaderBGColor1}" Offset="0.0" />
                     <GradientStop Color="{DynamicResource  grdHeaderBGColor2}" Offset="0.5" />
                     <GradientStop Color="{DynamicResource grdHeaderBGColor1}" Offset="1.0" />
                 </LinearGradientBrush>
             </Setter>
         </Style>
    

    然后你可以用新的样式覆盖它。 frmTest2GradientStyle 是我在 Application.Resources.

    中设置的样式
    frmTest2.Style = (Style)Application.Current.Resources["frmTest2GradientStyle"];
    
  2. 如果像下面这样在 Frame 中设置背景,则可以更改背景而不是 Background。

    <Frame x:Name="frmTest3" Style="{StaticResource wlHeaderGradient2}">
                 <Frame.Background>
                     <LinearGradientBrush EndPoint="0,1">
                         <GradientStop Color="{DynamicResource grdHeaderBGColor1}" Offset="0.0" />
                         <GradientStop Color="{DynamicResource  grdHeaderBGColor2}" Offset="0.5" />
                         <GradientStop Color="{DynamicResource grdHeaderBGColor1}" Offset="1.0" />
                     </LinearGradientBrush>
                 </Frame.Background>
             </Frame>
    

    更改代码中的背景:

         GradientStopCollection gradientStops = new GradientStopCollection();
         gradientStops.Add(new GradientStop() { Color = Color.Green, Offset = (float)0.0 });
         gradientStops.Add(new GradientStop() { Color = Color.Red, Offset = (float)0.5 });
         gradientStops.Add(new GradientStop() { Color = Color.Green, Offset = (float)1.0 });
    
         LinearGradientBrush linearGradientBrush = new LinearGradientBrush()
         {
             EndPoint = new Point(0, 1),
             GradientStops = gradientStops
         };
    
         frmTest3.Background = linearGradientBrush;