从视图模型属性获取背景颜色

huangapple go评论73阅读模式
英文:

Getting background color from view model property

问题

以下是翻译好的部分:

"Is it possible to get a control’s background color from a property in ViewModel?"

"ViewModel 中的属性是否可以用于获取控件的背景颜色?"

"The purpose is to be able to change color of Border or Button based on user actions. Because I’m using the MVVM approach, ideally, I simply set the background color of my control through a property in my view model."

"目的是根据用户的操作来更改BorderButton的颜色。因为我采用了MVVM方法,理想情况下,我只需通过视图模型中的属性来设置控件的背景颜色。"

"I tried the following but it didn’t work:"

"我尝试了以下方法,但没有成功:"

<Border
   BackgroundColor="{Binding MyBorderBackgroundColor}">
    <Label Text=“Hello World” />
</Border>
<Border
   BackgroundColor="{Binding MyBorderBackgroundColor}">
    <Label Text=“Hello World” />
</Border>

"In my view model, I use a string property and set it to either a color name such as Red or a Hex value such as #FF0000. I have an Init() method that I call from OnAppearing() and set the value -- see below:"

"在我的视图模型中,我使用一个string属性,并将其设置为颜色名称,如Red,或十六进制值,如#FF0000。我有一个Init()方法,我从OnAppearing()中调用它并设置这个值,如下所示:"

[ObservableProperty]
string myBorderBackgroundColor;
    
...
    
public void Init()
{
   MyBorderBackgroundColor = "Red"; // Or Hex value => MyBorderBackgroundColor = "#FF0000";
}
[ObservableProperty]
string myBorderBackgroundColor;
    
...
    
public void Init()
{
   MyBorderBackgroundColor = "Red"; // Or Hex value => MyBorderBackgroundColor = "#FF0000";
}

"The app simply ignores the color setting and defaults to page background. No error but just doesn't use the value set through the view model property."

"应用程序简单地忽略了颜色设置,并默认为页面背景。没有错误,但只是不使用通过视图模型属性设置的值。"

"Any suggestions?"

"有任何建议吗?"

英文:

Is it possible to get a control’s background color from a property in ViewModel?

The purpose is to be able to change color of Border or Button based on user actions. Because I’m using the MVVM approach, ideally, I simply set the background color of my control through a property in my view model.

I tried the following but it didn’t work:

<Border
   BackgroundColor="{Binding MyBorderBackgroundColor}">
    <Label Text=“Hello World” />
</Border>

In my view model, I use a string property and set it to either a color name such as Red or a Hex value such as #FF0000. I have an Init() method that I call from OnAppearing() and set the value -- see below:

[ObservableProperty]
string myBorderBackgroundColor;
    
...
    
public void Init()
{
   MyBorderBackgroundColor = "Red"; // Or Hex value => MyBorderBackgroundColor = "#FF0000";
}

The app simply ignores the color setting and defaults to page background. No error but just doesn't use the value set through the view model property.

Any suggestions?

答案1

得分: 5

您的备份属性是一个 string,但它应该是一个 Color。然而,我明白你可能认为这会起作用,因为在 XAML 中,你可以简单地将一个字符串添加到它。

背景

要理解为什么在 XAML 中可以工作,但在代码中不行,我们需要了解 TypeConverter。由于 XAML 只能包含字符串,我们必须找到一种将该字符串转换为实际可用类型的方法。通过 TypeConverter,我们就可以做到这一点。

在我们希望人们在 XAML 中使用字符串但仍然期望获得所期望的结果的对象上,我们添加了这个属性,这里是为 Color 添加的:

[TypeConverter(typeof(Converters.ColorTypeConverter))]
public class Color
{
   /// 类的实现
}

如果你好奇的话,这里是 [ColorTypeConverter完整实现

这意味着当 XAML 解析器找到这个属性以及相应的(字符串)值时,它将首先调用该 TypeConverter,这将导致具体类型,即我们的情况下是 Color 被使用。

当你像你现在这样进行绑定时,TypeConverter 不会被调用,因此现在我们将一个字符串值绑定到一个期望 Color 对象的属性,因此它不起作用。

修复

要修复这个问题,将备份属性更改为 Color 并进行初始化。

[ObservableProperty]
Color myBorderBackgroundColor;

// ...

public void Init()
{
   MyBorderBackgroundColor = Colors.Red; // 或十六进制值 => MyBorderBackgroundColor = Color.FromArgb("#FF0000");
}

你的 XAML 包含一个小错误,绑定周围没有引号。不确定是否在你的实际代码中出现了这个问题,但为了确保,确保在 BackgroundColor 的值周围有引号,如下所示:

<Border
   BackgroundColor="{Binding MyBorderBackgroundColor}">
    <Label Text="Hello World" />
</Border>
英文:

Your backing property is a string, while it should be a Color. However, I do understand you would think this works, because in XAML you can simply add a string to it.

Background

To understand why that works in XAML but not code, we'll have to learn about TypeConverter. Since XAML can only contain strings, we have to find a way to convert that string into a type that is actually useable. With a TypeConverter we do just that.

On an object where we expect people to use a string in XAML but still expect the desired outcome we add this attribute, here it is for Color:

[TypeConverter(typeof(Converters.ColorTypeConverter))]
public class Color
{
   /// The class
}

Here is the full implementation of ColorTypeConverter in case you're curious.

This means that when the XAML parser finds this property and the corresponding (string) value, it will invoke that TypeConverter first and that results into the concrete type, in our case Color, to be used.

When you do a binding like you're doing, the TypeConverter is not invoked, and thus we're now binding a string value to a property that expects a Color object and therefore: not working.

The Fix

To fix this, change the backing property to a Color and initialize it as such.

[ObservableProperty]
Color myBorderBackgroundColor;

// ...
    
public void Init()
{
   MyBorderBackgroundColor = Colors.Red; // Or Hex value =&gt; MyBorderBackgroundColor = Color.FromArgb(&quot;#FF0000&quot;);
}

Your XAML contains a small error with no quotes around the binding. Not sure if that is in your actual code, but just to be sure. Make sure there is quotes around the value of BackgroundColor like so:

&lt;Border
   BackgroundColor=&quot;{Binding MyBorderBackgroundColor}&quot;&gt;
    &lt;Label Text=&quot;Hello World&quot; /&gt;
&lt;/Border&gt;

答案2

得分: 1

首先,您需要确保使用双引号正确设置绑定:

&lt;Border
   BackgroundColor=&quot;{Binding MyBorderBackgroundColor}&quot;&gt;
    &lt;Label Text=“Hello World” /&gt;
&lt;/Border&gt;

然后,我建议在ViewModel中使用Color类型而不是string,因为这两种类型之间没有隐式转换。这也是我在自己的应用程序中的做法。

因此,您可以将您的代码更改为以下内容,并以多种不同的方式定义颜色(此列表不是最终的):

[ObservableProperty]
Color myBorderBackgroundColor;

//...

public void Init()
{
   // 使用十六进制值
   MyBorderBackgroundColor = Color.FromHex(&quot;#FF0000&quot;);

   // 解析字符串
   MyBorderBackgroundColor = Color.FromName(&quot;Red&quot;);

   // 使用RGB
   MyBorderBackgroundColor = Color.FromRgb(255,0,0);

   // 使用命名颜色
   MyBorderBackgroundColor = Colors.Red;

   //...
}

您可以在官方文档中找到有关颜色的更多信息。

英文:

First of all, you need to make sure that the binding is set up correctly using double quotes:

&lt;Border
   BackgroundColor=&quot;{Binding MyBorderBackgroundColor}&quot;&gt;
    &lt;Label Text=“Hello World” /&gt;
&lt;/Border&gt;

Then, I would recommend using the Color type in the ViewModel instead of a string since there is no implicit conversion between those types. That's how I am doing it in my own apps, too.

So, you could change your code to the following and define the color in a variety of different ways (the list is not final):

[ObservableProperty]
string myBorderBackgroundColor;
    
//...
    
public void Init()
{
   // use hex value
   MyBorderBackgroundColor = Color.FromArgb(&quot;#FF0000&quot;);

   // parse string
   MyBorderBackgroundColor = Color.Parse(&quot;Red&quot;);

   // use RGB
   MyBorderBackgroundColor = Color.FromRgb(255,0,0);

   // use named color
   MyBorderBackgroundColor = Colors.Red;

   //...
}

You can find more information about Colors in the official documentation.

huangapple
  • 本文由 发表于 2023年2月19日 16:23:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75498847.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定