我在数据绑定与自定义组件一起使用时遇到问题。
我创建了一个 IncrementValue 属性,每次单击按钮时该属性都会增加。
绑定到标签时会反映更改。但是,当我将其绑定到自定义组件中的可绑定属性时,它们不起作用。
在示例中,我构建了一个名为的自定义组件Card,它具有两个可绑定属性CardTitle和CardIncrement
由于我是 MAUI 甚至 Xamarin 的新手,我是否遗漏了一些东西。
以下代码片段的 Github 链接:https://github.com/814k31/DataBindingExample
卡.xaml.cs
namespace DataBindingExample;
public partial class Card : VerticalStackLayout
{
public static readonly BindableProperty CardTitleProperty = BindableProperty.Create(nameof(CardTitle), typeof(string), typeof(Card), string.Empty);
public static readonly BindableProperty CardIncrementProperty = BindableProperty.Create(nameof(CardIncrement), typeof(int), typeof(Card), 0);
public string CardTitle
{
get => (string)GetValue(CardTitleProperty);
set => SetValue(CardTitleProperty, value);
}
public int CardIncrement
{
get => (int)GetValue(CardIncrementProperty);
set => SetValue(CardIncrementProperty, value);
}
public Card()
{
InitializeComponent();
BindingContext = this;
}
}
Run Code Online (Sandbox Code Playgroud)
卡.xaml
<?xml version="1.0" encoding="utf-8" ?>
<VerticalStackLayout
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:databindingexample="clr-namespace:DataBindingExample"
x:DataType="databindingexample:Card"
x:Class="DataBindingExample.Card"
Spacing="25"
Padding="30,0"
VerticalOptions="Center"
BackgroundColor="red"
>
<Label
Text="{Binding CardTitle}"
SemanticProperties.HeadingLevel="Level1"
FontSize="32"
HorizontalOptions="Center"
/>
<Label
Text="{Binding CardIncrement}"
SemanticProperties.HeadingLevel="Level1"
FontSize="32"
HorizontalOptions="Center"
/>
</VerticalStackLayout>
Run Code Online (Sandbox Code Playgroud)
主页.xml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingExample.MainPage"
xmlns:DataBindingExample="clr-namespace:DataBindingExample"
xmlns:ViewModels="clr-namespace:DataBindingExample.ViewModels"
x:DataType="ViewModels:MainPageViewModel"
>
<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center"
>
<Label
Text="{Binding IncrementedValue}"
SemanticProperties.HeadingLevel="Level2"
FontSize="18"
HorizontalOptions="Center"
/>
<!-- Why doesnt this work? -->
<DataBindingExample:Card CardIncrement="{Binding IncrementedValue}" />
<Button
x:Name="CounterBtn"
Text="Click Me"
SemanticProperties.Hint="Counts the number of times you click"
Command="{Binding IncrementValueCommand}"
HorizontalOptions="Center"
/>
</VerticalStackLayout>
</ScrollView>
</ContentPage>
Run Code Online (Sandbox Code Playgroud)
Too*_*eve 14
制作自定义组件(包括 XAML)时,请勿设置BindingContext = this;.
原因:您希望组件使用与其所在页面相同的 BindingContext。如果您不在自定义组件中设置 BindingContext,这种情况会自动发生。
\n但是,删除此行会破坏组件的所有 xaml Bindings;您需要向 xaml添加一些内容来解决此问题。
\n或者换句话说:如何从 XAML 中引用卡的属性?请参阅下一节。
\n通过 x:Name 访问组件属性
\n解决方案:为自定义组件(卡)提供一个x:Name,并将其作为这些绑定的“源”:
<VerticalStackLayout\n ...\n x:Name="me" <-- IMPORTANT! Change name as desired.\n x:Class="DataBindingExample.Card"\n>\n ...\n <Label Text="{Binding CardIncrement, Source={x:Reference me}}"\n ...\nRun Code Online (Sandbox Code Playgroud)\n请注意此解决方案的两个部分:
\nx:Name="mynamehere".Binding,假设该组件是源:\n , Source={x:Reference mynamehere}。Sourcebefore Path:"{Binding Source={x:Reference me}, CardIncrement}"Path:"{Binding Source={x:Reference me}, Path=CardIncrement}"可选(罕见):如果自定义组件具有“ViewModel”:
\n重要提示:即使您正在使用 MVVM,自定义组件通常也没有视图模型。相反,它的行为是由包含页面使用 BindableProperties 控制的。如相关代码所示。
\n对于那些将组件的数据和数据操作方法分解为单独的(“视图模型”)类的人来说,此处显示的技术很方便。
\n要使 BindableProperties 发挥作用,请回忆上面的内容:
\n\n\n不要设置 BindingContext(以便组件可以轻松访问页面的 BindingContext)。
\n
因此,在这种技术中,我们不将 ViewModel 设置为 BindingContext。
\n如何访问这个ViewModel?
\n通过将其保存为组件的属性;例如:
\npublic partial class MyComponent : ContentView\n{\n private MyViewModel VM;\n\n public void MyComponent()\n {\n InitializeComponent();\n\n VM = new MyViewModel();\n //DO NOT DO "BindingContext = VM;"\n }\n\npublic class MyViewModel : ObservableObject\n{\n [ObservableProperty]\n SomeType someProperty; // This is field. Property "SomeProperty" is generated.\n}\nRun Code Online (Sandbox Code Playgroud)\n重要提示:需要x:Name在组件上定义。请参阅此答案的前面部分。
然后在 xaml 中,我们使用.符号访问 VM 的属性:
<Label Text="{Binding VM.SomeProperty, Source={x:Reference me}}"\nRun Code Online (Sandbox Code Playgroud)\n另一种方法是Source={RelativeSource Self}
<SomeElement SomeAttribute="{Binding MyProperty, Source={RelativeSource Self}}" />\n <-- OPTIONAL -->\n <SomeElement SomeAttribute="{Binding VM.SomeProperty, Source={RelativeSource Self}}" />\nRun Code Online (Sandbox Code Playgroud)\n我个人不使用这种语法,因为有人阅读时可能不确定“Self”指的是什么。是“SomeElement”(包含“Binding”表达式的元素)吗?它是周围的“DataTemplate”(如果有)吗?它是 XAML 文件的根吗?我\xe2\x80\x99m不会回答这个问题;使用 x:Name 代替。
\n| 归档时间: |
|
| 查看次数: |
2915 次 |
| 最近记录: |