【问题标题】:How to bind a control to a view model when page binding context is set to a different view model in Xamarin在 Xamarin 中将页面绑定上下文设置为不同的视图模型时如何将控件绑定到视图模型
【发布时间】:2021-04-10 01:40:22
【问题描述】:

我的内容页面绑定到一个视图模型,但现在我需要将一些组件绑定到不同的视图模型。我的问题是,因为我已将页面的 BindingContext 绑定到视图模型,所以当我尝试将元素绑定到第二个视图模型时,{Binding propertyname} 语句会在视图模型中查找绑定到绑定上下文。

所以我的问题是:当 bindingcontext 设置为不同的视图模型时,如何简单地将元素绑定到视图模型而不是 bindingcontext?

我尝试过的东西不起作用

  1. 定义了第二个视图模型。并尝试通过静态资源进行绑定

代码

    <ContentPage.Resources>
        <ResourceDictionary>
            <selectedDeal:DealsMViewModel x:Name="SelectedDeal" x:Key="SelectedDeal"/>
        </ResourceDictionary>
    </ContentPage.Resources>

代码

 <Image
     x:Name="CompanyImage"
     HeightRequest="200"
     Aspect="AspectFill"
     Source="{Binding Source={StaticResource SelectedDeal}, Path=DealImage}" />
  1. 我已将图像元素放入堆栈布局,设置 StackLayout 的 BindingContext 和 尝试像这样绑定:

代码

 <Image
         x:Name="CompanyImage"
         HeightRequest="200"
         Aspect="AspectFill"
         Source="{Binding DealImage}"/>
     

我有两种方法使绑定工作

  1. 将第二个视图模型定义为绑定到 BindingContext 的第一个视图模型的属性,然后像这样实现图像

代码

<Image
x:Name="CompanyImage"
HeightRequest="200"
Aspect="AspectFill"
Source="{Binding secondViewModel.DealImage}"/>
  1. 在后面的代码中以编程方式设置图像源。

代码

CompanyImage.Source = selectedDeal.DealImage;

但我真正想要实现的是尽可能在 XAML 部分中学习执行此操作的方法!非常感谢任何帮助!

【问题讨论】:

  • 如果你有一个特定的页面显示,有它自己的视图模型,那你为什么不把 DealImage 属性放在里面呢?理想情况下,每个页面应该只知道自己的视图模型,而不是假设堆栈上还有其他页面打开。我看到的最佳方式是您页面的视图模型将第二个视图模型作为其子视图。
  • 最好创建一个自定义控件(具有自己的视图模型),然后通过 xaml 访问它,如&lt;SelectedDeal DealImage={Binding SomeSource}/&gt; 并将来自 DealsMViewModel 的逻辑放入 SelectedDeal 控件中?另一个想法是,如果您尝试访问的视图模型是嵌套的,请使用 Binding Source={RelativeSource AncestorType={x:Type ...}}。

标签: c# xamarin xamarin.forms


【解决方案1】:

有几种方法可以实现您的要求...我将解释我处理 ViewModel 绑定的方式...

  1. 使用 DependencyService 容器管理器创建新类以保存对每个视图模型的引用。我称之为 ViewModelLocator。例如:
public class ViewModelLocator
    {
        public ViewModelLocator()
        {
            DependencyService.Register<ILogService, LogService>();
            if (!DesignMode.IsDesignModeEnabled)
            {
                DependencyService.Register<IDataStore, MockDataStore>();
            }
            else
            {
                DependencyService.Register<IDataStore, DesignDataStore>();
            }
            DependencyService.Register<LoginViewModel>();
            DependencyService.Register<AboutViewModel>();
            DependencyService.Register<SettingsViewModel>();
        }
        public LoginViewModel Login => DependencyService.Get<LoginViewModel>();
        public AboutViewModel About => DependencyService.Get<AboutViewModel>();
        public SettingsViewModel Settings => DependencyService.Get<SettingsViewModel>();
    }
  1. 在您的 App.xaml 中引用此类

  2. 这将允许您通过仅引用定位器来绑定到任何视图模型。 在下面的示例中,您的“主要”ViewModel 是 LoginViewModel,但下面的按钮绑定到 About ViewModel

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Test.Views.LoginPage"
             BindingContext="{Binding Login, Source={StaticResource Locator}}"
             Title="LoginPage">
    <ScrollView>
        <Grid Margin="10,20,10,10" RowDefinitions="Auto,Auto,Auto,Auto">
            <Label Grid.Row="0" Text="Username:" TextColor="Black" FontSize="14"/>
            <Entry Grid.Row="1" x:Name="usernameEditor" Text="{Binding Username}" ClearButtonVisibility="WhileEditing" />
            <Label Grid.Row="2" Text="Password:" TextColor="Black" FontSize="14"/>
            <Entry Grid.Row="3" x:Name="passwordEditor" Text="{Binding Password}" IsPassword="True" ClearButtonVisibility="WhileEditing" />
            <Button Grid.Row="6" Text="Login" Command="{Binding About.LoginCommand, Source={StaticResource Locator}}"/>
        </Grid>
    </ScrollView>
</ContentPage>

【讨论】:

  • 这实际上是非常有用的coden-p,谢谢!我正在做类似的事情。但是说在这个内容页面中你还需要从另一个服务中提取数据,你会怎么处理呢?
  • 这实际上是非常有用的coden-p,谢谢!我正在做类似的事情。但是说在这个内容页面中你还需要从另一个服务中提取数据,你会怎么处理呢?
  • 如果我们谈论的是服务,那么可以使用容器管理器从任何 ViewModel 访问它。即 DependencyService.Get().Info("Some info text");。如果我们谈论的是绑定(属性或命令),这在上面的 Button 绑定中显示。基本上你使用定位器来访问任何 ViewModel。
猜你喜欢
  • 2020-01-29
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
  • 2020-06-20
相关资源
最近更新 更多