根据数据绑定的值设置背景颜色

15

我以前看过一些答案,但没有真正帮助到我。

我有一个名为DecideModel的类(这将是从数据库检索的数据集,但为了这个问题的目的,我添加了一个ObservableCollection)。

static DecideModel()
    {
        All = new ObservableCollection<DecideModel>
        {
            new DecideModel
            {
                DatePerformed = new DateTime(2015, 4, 06),
                Result = "Maybe"
            },
            new DecideModel
            {
                DatePerformed = new DateTime(2015, 4, 05),
                Result = "No"
            },
            new DecideModel
            {
                DatePerformed = new DateTime(2015, 4, 04),
                Result = "Yes"
            }
        };
    }

    public DateTime DatePerformed { set; get; }

    public string  Result { set; get; }

    public static IList<DecideModel> All { set; get; }
}

在我的 XAML 代码中,我有:

<ContentPage.Resources>
    <ResourceDictionary>
        <Color x:Key="Maybe">#ffddbc21</Color>
        <Color x:Key="Yes">#3CB371</Color>
        <Color x:Key="No">#B22222</Color>
        <Color x:Key="Depends">#ffd78800</Color>
    </ResourceDictionary>
</ContentPage.Resources>

<Label Text="{Binding Result}" HorizontalOptions="FillAndExpand" BackgroundColor="{StaticResource {BindingSource Result}}" />

我正在尝试根据从对象获得的结果动态设置标签的背景色。

如果您有任何关于如何实现此目的的想法,请告诉我。 我正在寻找任何可用的有用选项。

3个回答

28
您可能需要使用一个“ValueConverter”。您现在所做的是将背景颜色设置为“Maybe”、“No”或“Yes”,这显然不是一种颜色。
您需要将该值转换为一种颜色。您可以像这样操作。
创建一个实现“IValueConverter”接口的新类。它可能看起来像这样:
public class YesNoMaybeToColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
            switch(value.ToString().ToLower())
            {
                    case "yes":
                        return Color.Green;
                    case "no":
                        return Color.Red;
                    case "maybe":
                        return Color.Orange;
            }

            return Color.Gray;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
            // You probably don't need this, this is used to convert the other way around
            // so from color to yes no or maybe
            throw new NotImplementedException();
    }
}

然后将此类作为静态资源添加到您的XAML页面中,如下所示:
<ContentPage.Resources>
   <!-- Add this line below -->
   <local:YesNoToBooleanConverter x:Key="YesNoMaybeToColorConverter" />
   <!-- You can remove the underneath -->
    <!--<ResourceDictionary>
        <Color x:Key="Maybe">#ffddbc21</Color>
        <Color x:Key="Yes">#3CB371</Color>
        <Color x:Key="No">#B22222</Color>
        <Color x:Key="Depends">#ffd78800</Color>
    </ResourceDictionary>-->
</ContentPage.Resources>

现在,您需要在绑定中告诉它使用哪个转换器。请按以下方式进行:

<Label Text="{Binding Result}" HorizontalOptions="FillAndExpand" BackgroundColor="{Binding Result, Converter={StaticResource YesNoMaybeToColorConverter}}" />

现在应该看到Result字段中的值,将其通过您定义的转换器并返回相应于该值的颜色。


如果我想保留默认值呢?也许它不是Color.Gray。有Initial或者其他什么吗? - Mihai Socaciu

17

如果您希望通过纯XAML的方式实现此目标而不需要太多开销,您可以使用DataTrigger。请注意,对于每个触发器,您可以添加所需数量的Setter,使其比先前建议的解决方案更加灵活,同时将视图逻辑保留在应该存在的视图中。

<Label Text="{Binding Result}" HorizontalOptions="FillAndExpand">
    <Label.Triggers>
        <DataTrigger TargetType="Label" Binding="{Binding Result}" Value="Yes">
            <Setter Property="BackgroundColor" Value="#3CB371" />
        </DataTrigger>
        <DataTrigger TargetType="Label" Binding="{Binding Result}" Value="No">
            <Setter Property="BackgroundColor" Value="#B22222" />
        </DataTrigger>
        <DataTrigger TargetType="Label" Binding="{Binding Result}" Value="Maybe">
            <Setter Property="BackgroundColor" Value="#ddbc21" />
        </DataTrigger>
        <DataTrigger TargetType="Label" Binding="{Binding Result}" Value="Depends">
            <Setter Property="BackgroundColor" Value="#d78800" />
        </DataTrigger>
    </Label.Triggers>
</Label>

请注意,您可能可以通过将BackgroundColor属性设置为合理的默认值(在这种情况下可能是“Depends”)来省略其中一个触发器。


1
这对我有所帮助。我喜欢这个项目,适用于简单情况的快速解决方案。谢谢。 - Cobysan

1
我找到了另外两种管理这个的选项,因为有时候我们需要改变不仅仅是颜色还包括字体和其他值。 首先,你需要像这样给你的控件添加名称:
<Label x:Name="MyLabel" Text="{Binding Result}" HorizontalOptions="FillAndExpand"/>

1. 您可以像这样在代码后端设置颜色和其他属性,但这种方式需要一些时间来更新,因此当 Text 属性刚刚更新时,它并不是最佳选择。

protected override void OnAppearing()
{
    if (this.MyLabel.Text.Contains("yes")
    {
        this.MyLabel.TextColor = Color.FromHex("#98ee99");
    }
    else
    {
        this.MyLabel.TextColor = Color.FromHex("#ff867c");
    }
}

2. 另一种方法是使用Prism EventAggregator,我猜在Xamarin.Forms中它是Messaging Center。这里有一个使用Prism的好例子

在这种情况下,您应该从项目中的任何地方发送带有值的事件,例如当它应该已经更新时。

_evenAggregator.GetEvent<MyEvent>().Publish(Result);

然后,您应该订阅事件,以在需要接收新值的地方接收它。在这种情况下,应该在代码后台类中的OnAppearing方法中进行。

void UpdateColor(string result)
{
     if(result.Contains("yes")
     {
         this.MyLabel.TextColor = Color.FromHex("#98ee99");
     }
     else
     {
         this.MyLabel.TextColor = Color.FromHex("#ff867c");
     }
}

protected override void OnAppearing()
{
    base.OnAppearing();
    _eventAggregator.GetEvent<MyEvent>().Subscribe(UpdateColor);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接