XamarinForms ContentView 使用 CommunityToolkit.Mvvm 进行绑定。

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

XamarinForms ContentView binding using CommunityToolkit.Mvvm

问题

以下是翻译好的部分:

我有一个包含"ContentView Recommendations"的MainPage。MainPage有自己的ViewModel,与Recommendations视图相同。在MainPage的OnAppearing事件中,我需要调用RecommendationViewModel中的InitializeAsync()方法,以填充Recommendations ObservableColllection数据。到目前为止一切都很好,除了我的数据没有显示在ListView中。

我正在使用CommunityToolkit.Mvvm。

这是我的代码:

-- MainPage.xaml.cs

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:vm="clr-namespace:ApeOdds.ViewModels"
    xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
    ios:Page.UseSafeArea="True"
    x:Name="Main"
    x:Class="ApeOdds.Views.MainPage">

    <ContentPage.BindingContext>
        <vm:MainViewModel />
    </ContentPage.BindingContext>

    <ContentPage.Content>
        <controls:RecommendationsView />
    </ContentPage.Content>
</ContentPage>

-- MainPage.xaml.cs

public partial class MainPage : ContentPage
{
    public MainViewModel ViewModel => (MainViewModel)BindingContext;

    public MainPage()
    {
        InitializeComponent();
        BindingContext = Ioc.Default.GetRequiredService<MainViewModel>();
    }

    protected override async void OnAppearing()
    {
        var recommendationVm = Ioc.Default.GetRequiredService<RecommendationViewModel>();
        await recommendationVm.InitializeAsync(); 
        //var recommendations = recommendationVm.Recommendations; -- 我有推荐数据在这里,但它们没有显示
        base.OnAppearing();
    }
}

-- MainViewModel.cs

public partial class MainViewModel : ObservableObject
{
    public MainViewModel()
    {
    }
}

—- Recommendations.xaml

<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:ApeOdds.ViewModels"
             x:Class="ApeOdds.Controls.RecommendationsView"
             x:Name="rootView">

    <ContentView.BindingContext>
        <vm:RecommendationViewModel />
    </ContentView.BindingContext>
    <ListView ItemsSource="{Binding Recommendations}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Label Text="{Binding Id}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentView>

—- Recommendations.xaml.cs

public partial class RecommendationsView : ContentView
{
    public RecommendationViewModel ViewModel => (RecommendationViewModel)BindingContext;

     public RecommendationsView()
     {
         InitializeComponent();
         BindingContext = Ioc.Default.GetRequiredService<RecommendationViewModel>();
     }
}

-- RecommendationViewModel.cs

public partial class RecommendationViewModel : ObservableObject
{
    public ObservableCollection<Recommendation> Recommendations { get; set; }

    public RecommendationViewModel()
    {
    }

    public async Task InitializeAsync()
    {
        var recommendations = DummyData.CreateDummyRecommendations();
        Recommendations = new ObservableCollection<Recommendation>(recommendations);
        OnPropertyChanged(nameof(Recommendations));
    }
}

-- App.xaml.cs

public partial class App : Application
{

    public App ()
    {
        InitializeComponent();

        Ioc.Default.ConfigureServices(
            new ServiceCollection()
            .AddTransient<BaseViewModel>()
            .AddTransient<MainViewModel>()
            .AddTransient<RecommendationViewModel>()
            .RegisterRefitService()
            .BuildServiceProvider());

        MainPage = new AppShell();
    }

     protected override void OnStart ()
     {
     }

     protected override void OnSleep ()
     {
     }

     protected override void OnResume ()
     {
     }
}
英文:

I have MainPage which contains ContentView Recommendations. MainPage has its own ViewModel, the same as the Recommendations view. In the OnAppearing event of MainPage, I need to call InitializeAsync() method from RecommendationViewModel in order to populate Recommendations ObservableColllection data. Everything is okay so far, except my data is not shown in the ListView.

I'm using CommunityToolkit.Mvvm.

Here is my code:

-- MainPage.xaml.cs

&lt;ContentPage
    xmlns=&quot;http://xamarin.com/schemas/2014/forms&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
    xmlns:vm=&quot;clr-namespace:ApeOdds.ViewModels&quot;
    xmlns:ios=&quot;clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core&quot;
    ios:Page.UseSafeArea=&quot;True&quot;
    x:Name=&quot;Main&quot;
    x:Class=&quot;ApeOdds.Views.MainPage&quot;&gt;

    &lt;ContentPage.BindingContext&gt;
        &lt;vm:MainViewModel /&gt;
    &lt;/ContentPage.BindingContext&gt;

    &lt;ContentPage.Content&gt;
    	&lt;controls:RecommendationsView /&gt;
    &lt;/ContentPage.Content&gt;
&lt;/ContentPage&gt;

-- MainPage.xaml.cs

public partial class MainPage : ContentPage
{
    public MainViewModel ViewModel =&gt; (MainViewModel)BindingContext;

    public MainPage()
    {
        InitializeComponent();
        BindingContext = Ioc.Default.GetRequiredService&lt;MainViewModel&gt;();
    }

    protected override async void OnAppearing()
    {
        var recomendationVm = Ioc.Default.GetRequiredService&lt;RecommendationViewModel&gt;();
        await recomendationVm.InitializeAsync(); 
        //var recomendations = recomendationVm.Recommendations; -- I have recommendations data here, but they are not displayed
        base.OnAppearing();
    }
}

-- MainViewModel.cs

public partial class MainViewModel : ObservableObject
{
    public MainViewModel()
    {
    }
}

—- Recommendations.xaml

&lt;ContentView xmlns=&quot;http://xamarin.com/schemas/2014/forms&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             xmlns:vm=&quot;clr-namespace:ApeOdds.ViewModels&quot;
             x:Class=&quot;ApeOdds.Controls.RecommendationsView&quot;
             x:Name=&quot;rootView&quot;&gt;

    &lt;ContentView.BindingContext&gt;
        &lt;vm:RecommendationViewModel /&gt;
    &lt;/ContentView.BindingContext&gt;
    &lt;ListView ItemsSource=&quot;{Binding Recommendations}&quot;&gt;
        &lt;ListView.ItemTemplate&gt;
            &lt;DataTemplate&gt;
                &lt;Label Text=&quot;{Binding Id}&quot;/&gt;
            &lt;/DataTemplate&gt;
        &lt;/ListView.ItemTemplate&gt;
    &lt;/ListView&gt;
&lt;/ContentView&gt;

—- Recommendations.xaml.cs

public partial class RecommendationsView : ContentView
{
    public RecommendationViewModel ViewModel =&gt; (RecommendationViewModel)BindingContext;

     public RecommendationsView()
     {
         InitializeComponent();
         BindingContext = Ioc.Default.GetRequiredService&lt;RecommendationViewModel&gt;();
     }
}

-- RecommendationViewModel.cs

public partial class RecommendationViewModel : ObservableObject
{
    public ObservableCollection&lt;Recommendation&gt; Recommendations { get; set; }

	public RecommendationViewModel()
    {
    }

    public async Task InitializeAsync()
    {
	    var recommendations = DummyData.CreateDummyRecommendations();
        Recommendations = new ObservableCollection&lt;Recommendation&gt;(recommendations);
        OnPropertyChanged(nameof(Recommendations));
    }
}

-- App.xaml.cs

public partial class App : Application
{

    public App ()
    {
        InitializeComponent();

        Ioc.Default.ConfigureServices(
            new ServiceCollection()
            .AddTransient&lt;BaseViewModel&gt;()
            .AddTransient&lt;MainViewModel&gt;()
            .AddTransient&lt;RecommendationViewModel&gt;()
            .RegisterRefitService()
            .BuildServiceProvider());


        MainPage = new AppShell();
    }

     protected override void OnStart ()
     {
     }

     protected override void OnSleep ()
     {
     }

     protected override void OnResume ()
     {
     }
}

答案1

得分: 1

您可以使用BindableProperty来实现这一功能。

根据您的代码,我创建了一个演示来实现这个功能。我们需要在ContentView(RecommendationsView.xaml.cs)中添加一个Bindable Property。

您可以参考以下代码:

RecommendationsView.xaml.cs

public partial class RecommendationsView : ContentView 
{
    public RecommendationsView()
    {
        InitializeComponent();
    }

    public static readonly BindableProperty myViewModelProperty =
        BindableProperty.Create(
            nameof(myViewModel),
            typeof(MainViewModel),
            typeof(RecommendationsView),
            null);

    public MainViewModel myViewModel
    {
        set { SetValue(myViewModelProperty, value); }
        get { return (MainViewModel)GetValue(myViewModelProperty); }
    }
}

RecommendationsView.xaml

<?xml version="1.0" encoding="UTF-8"?> 
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FormContentViewApp.RecommendationsView"
             x:Name="myControlView"
             >
  <ContentView.Content>
        <ListView ItemsSource="{Binding Source={x:Reference myControlView}, Path=myViewModel.Items}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                      <Label Text="{Binding Id}"/>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentView.Content>
</ContentView>

MainViewModel.cs

public class MainViewModel 
{
    public ObservableCollection<Item> Items { get; set; }

    public MainViewModel() {
        Items = new ObservableCollection<Item>();

        Items.Add(new Item { Id = 1 });
        Items.Add(new Item { Id = 2 });
        Items.Add(new Item { Id = 3 });
    }
}

public class Item 
{
    public int Id { get; set; }
}

使用示例:

<?xml version="1.0" encoding="utf-8" ?> 
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:local="clr-namespace:FormContentViewApp"
             x:Class="FormContentViewApp.MainPage"
             x:Name="mainpage"
             >

    <ContentPage.BindingContext>
        <local:MainViewModel></local:MainViewModel>
    </ContentPage.BindingContext>

    <StackLayout Orientation="Vertical">
        <local:RecommendationsView  myViewModel="{Binding Path=BindingContext, Source={x:Reference mainpage}}">
        </local:RecommendationsView>
    </StackLayout>
</ContentPage>

注意:

不要忘记在ListView的DataTemplate元素中添加<ViewCell>,否则代码将抛出错误。

英文:

You can use BindableProperty to achieve this.

Based on your code, I created a demo to achieve this function.We need to add a Bindable Property to the ContentView (RecommendationsView.xaml.cs).

You can refer to the following code:

RecommendationsView.xaml.cs

 public partial class RecommendationsView : ContentView 
  {
    public RecommendationsView()
    {
        InitializeComponent();
    }

    public static readonly BindableProperty myViewModelProperty =
BindableProperty.Create(
    nameof(myViewModel),
    typeof(MainViewModel),
    typeof(RecommendationsView),
    null);

    public MainViewModel myViewModel
    {
        set { SetValue(myViewModelProperty, value); }
        get { return (MainViewModel)GetValue(myViewModelProperty); }
    }
}

RecommendationsView.xaml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; 
&lt;ContentView xmlns=&quot;http://xamarin.com/schemas/2014/forms&quot; 
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;FormContentViewApp.RecommendationsView&quot;
             x:Name=&quot;myControlView&quot;
             &gt;
  &lt;ContentView.Content&gt;
        &lt;ListView ItemsSource=&quot;{Binding Source={x:Reference myControlView}, Path=myViewModel.Items }&quot;&gt;
            &lt;ListView.ItemTemplate&gt;
                &lt;DataTemplate&gt;
                    &lt;ViewCell&gt;
                      &lt;Label Text=&quot;{Binding Id}&quot;/&gt;
                    &lt;/ViewCell&gt;
                &lt;/DataTemplate&gt;
            &lt;/ListView.ItemTemplate&gt;
        &lt;/ListView&gt;
    &lt;/ContentView.Content&gt;
&lt;/ContentView&gt;

MainViewModel.cs

public class MainViewModel 
{
    public ObservableCollection&lt;Item&gt; Items { get; set; }

    public MainViewModel() {
        Items= new ObservableCollection&lt;Item&gt;();

        Items.Add(new Item { Id = 1});
        Items.Add(new Item { Id = 2});
        Items.Add(new Item { Id = 3});
    }
}

public class Item 
{
    public int Id { get; set; }
}

Usage example:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt; 
&lt;ContentPage xmlns=&quot;http://xamarin.com/schemas/2014/forms&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot; 
             xmlns:local=&quot;clr-namespace:FormContentViewApp&quot;
             x:Class=&quot;FormContentViewApp.MainPage&quot;
             x:Name=&quot;mainpage&quot;
             &gt;

    &lt;ContentPage.BindingContext&gt;
        &lt;local:MainViewModel&gt;&lt;/local:MainViewModel&gt;
    &lt;/ContentPage.BindingContext&gt;

    &lt;StackLayout Orientation=&quot;Vertical&quot;&gt;
        &lt;local:RecommendationsView  myViewModel=&quot;{Binding Path=BindingContext, Source={x:Reference mainpage}}&quot;&gt;
        &lt;/local:RecommendationsView&gt;
    &lt;/StackLayout&gt;
&lt;/ContentPage&gt;

Note:

Do not forget to add &lt;ViewCell&gt; inside of element DataTemplate for your ListView. Otherwise, the code will throw an error.

huangapple
  • 本文由 发表于 2023年8月10日 12:15:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76872617.html
匿名

发表评论

匿名网友

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

确定