英文:
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."
"目的是根据用户的操作来更改Border
或Button
的颜色。因为我采用了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 => MyBorderBackgroundColor = Color.FromArgb("#FF0000");
}
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:
<Border
BackgroundColor="{Binding MyBorderBackgroundColor}">
<Label Text="Hello World" />
</Border>
答案2
得分: 1
首先,您需要确保使用双引号正确设置绑定:
<Border
BackgroundColor="{Binding MyBorderBackgroundColor}">
<Label Text=“Hello World” />
</Border>
然后,我建议在ViewModel中使用Color
类型而不是string
,因为这两种类型之间没有隐式转换。这也是我在自己的应用程序中的做法。
因此,您可以将您的代码更改为以下内容,并以多种不同的方式定义颜色(此列表不是最终的):
[ObservableProperty]
Color myBorderBackgroundColor;
//...
public void Init()
{
// 使用十六进制值
MyBorderBackgroundColor = Color.FromHex("#FF0000");
// 解析字符串
MyBorderBackgroundColor = Color.FromName("Red");
// 使用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:
<Border
BackgroundColor="{Binding MyBorderBackgroundColor}">
<Label Text=“Hello World” />
</Border>
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("#FF0000");
// parse string
MyBorderBackgroundColor = Color.Parse("Red");
// 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论