【问题标题】:Xamarin Forms Binding cannot be converted to typeXamarin 表单绑定无法转换为类型
【发布时间】:2021-09-25 16:06:38
【问题描述】:

Xamarin 表单的新手,在过去一天半的时间里试图弄清楚为什么我的某些绑定有效而其他绑定无效。它们的构造方式相同,但行为不同。大多数元素都绑定到我创建的可观察对象集合,这些对象是从我的 API 中的 ENUMS 中提取的。 XAML 选择器正确加载了我的集合——当我的应用程序正在运行并且我单击选择器时,我可以很好地查看列表。问题是 SelectedItem 的绑定。标签类型选择器正确显示所选项目,模拟类型选择器不显示我选择的项目 - 它是空白的(当我单击选择器时,集合仍然显示,只是所选项目是空白的)。这两个属性在我创建的服务中以相同的方式同时设置,以实现与模型中的属性交互的方法。然后,视图模型创建该服务的实例以访问属性。需要注意的一件奇怪的事情是,当热重载正在运行并且我删除然后重新添加此行时: SelectedItem="{Binding MyItemSimulationType}" 它可以工作!但是一旦我关闭程序并重新运行应用程序,所选项目再次为空白:/

输出窗口显示以下内容:

[0:] Binding: '' cannot be converted to type 'TagType'
[0:] Binding: '' cannot be converted to type 'SimulationType'

奇怪的部分是 TagType 的绑定有效而 SimulationType 无效。这是 XAML:

 <RefreshView x:DataType="local:ReadWriteViewModel" Command="{Binding LoadReadWriteValuesCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
    <ScrollView>
        <StackLayout Padding="10">

            <!--Item Properties-->
            <Frame>
                <StackLayout>
                    <Label Text="Item" FontSize="Subtitle" TextColor="Black" VerticalTextAlignment="Center" />

                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="auto" />
                            <RowDefinition Height="auto" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="auto"/>
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>

                        <!--Tag Type-->
                        <Label Grid.Row="0" Grid.Column="0" Text="Tag Type" VerticalTextAlignment="Center" HorizontalTextAlignment="End"/>
                        <Picker Grid.Row="0" Grid.Column="1" FontSize="Small" ItemsSource="{Binding MyItemHWTagTypes}" SelectedItem="{Binding MyItemHWTagType}" >
                            <Picker.Items></Picker.Items>
                        </Picker>

                        <!--Simulation Type-->
                        <Label Grid.Row="1" Grid.Column="0" Text="Simulation Type" VerticalTextAlignment="Center" HorizontalTextAlignment="End" />
                        <Picker Grid.Row="1" Grid.Column="1" FontSize="Small" ItemsSource="{Binding MyItemSimulationTypes}" SelectedItem="{Binding MyItemSimulationType}" HorizontalOptions="FillAndExpand">
                            <Picker.Items></Picker.Items>
                        </Picker>
                    </Grid>
                </StackLayout>
            </Frame>             
        </StackLayout>
    </ScrollView>
</RefreshView>

视图模型:

    private ObservableCollection<TagType> _itemHWTagTypes;
    private TagType _itemHWTagType;
    private ObservableCollection<SimulationType> _itemSimulationTypes;
    private SimulationType _itemSimulationType;

    public ObservableCollection<TagType> MyItemHWTagTypes
    {
      get => _itemHWTagTypes;
      set => SetProperty(ref _itemHWTagTypes, value);
    }

    public TagType MyItemHWTagType
    {
      get => _itemHWTagType;
      set => SetProperty(ref _itemHWTagType, value);
    }

    public ObservableCollection<SimulationType> MyItemSimulationTypes
    {
      get => _itemSimulationTypes;
      set => SetProperty(ref _itemSimulationTypes, value);
    }

    public SimulationType MyItemSimulationType
    {
      get => _itemSimulationType;
      set => SetProperty(ref _itemSimulationType, value);
    }

   public Command LoadReadWriteValuesCommand { get; }

   public ReadWriteViewModel()
    {

      //Load Model
      LoadReadWriteValuesCommand = new Command(async () => await         ExecuteLoadReadWriteValuesCommand());
    }

async Task ExecuteLoadReadWriteValuesCommand()
    {
      IsBusy = true;

      try
      {
        var asc = await ASCService.GetASCObjectAsync();
    
          // ----- Set Item properties to default values in model
          MyItemHWTagTypes = asc.ModelItemHWTagTypes;
          MyItemHWTagType = asc.ModelItemHWTagType;
          MyItemSimulationTypes = asc.ModelItemSimulationTypes;
          MyItemSimulationType = asc.ModelItemSimulationType;
     }
      catch (TaskCanceledException tcex)
      {
        Debug.WriteLine(tcex);
      }
      finally
      {
        IsBusy = false;
      }
    }

如果需要更多代码,请告诉我,我尝试在此处的示例代码中保持简化,并删除了与我的问题无关的额外代码。我在 ExecuteLoadReadWriteValuesCommand() 中的所有属性都设置正确,所以我确信这不是问题。 我的输出窗口中也收到了很多其他垃圾邮件,我认为这些消息不相关,但也许?这些是看起来可能有问题的:

[TabLayout] MODE_SCROLLABLE + GRAVITY_FILL is not supported, GRAVITY_START will be used instead
[Choreographer] Skipped 38 frames!  The application may be doing too much work on its main thread.
[OpenGLRenderer] Davey! duration=1656ms; Flags=0, IntendedVsync=1769860264400, Vsync=1770843597694, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=1770846662700, AnimationStart=1770846714100, PerformTraversalsStart=1770847196400, DrawStart=1771495643200, SyncQueued=1771503136700, SyncStart=1771503918600, IssueDrawCommandsStart=1771504436800, SwapBuffers=1771515968100, FrameCompleted=1771517457000, DequeueBufferDuration=303000, QueueBufferDuration=902000, 

【问题讨论】:

  • 要绑定SelectedItem 的项目需要是ItemsSource 集合中包含的元素
  • @Jason 这是...
  • 它必须是同一个实例,而不是同一个对象的两个副本。尝试设置 MyItemSimulationType = MyItemSimulationTypes[0] 来检查
  • 首先按照杰森的建议去做,排除一些可能性。然后 1) 您已验证 asc.ModelItemSimulationType 不为空? 2) 何时/如何调用LoadReadWriteValuesCommand?在构建视图时?还是 OnAppearing?还是以后? 3) 作为测试,在 VM 构造函数中硬编码一个列表,并注释掉对服务的延迟调用——它有效吗? 4)切换分配顺序,所以MyItemSimulationType设置在MyItemHWTagType之前 - 症状会改变吗?
  • 5) ExecuteLoadReadWriteValuesCommand 中的断点,位于设置 Item 属性的第一行。检查您所在的线程 - 它应该是 UI 线程。

标签: c# xaml xamarin.forms mvvm data-binding


【解决方案1】:

我想通了!您不能将绑定属性设置为集合的位置 [0] 中的值。我通过并将默认值设置为位置 [1] 并且它起作用了!不确定这是一个错误还是它是如何工作的,但很高兴这一切都结束了。

【讨论】:

  • 很高兴您找到了解决方法。这是我的理论为什么会这样:分配给项目 [0] 被认为是“没有改变”,因为视图已经默认为“0”。当您对 [0] 进行 SECOND 分配时,它会导致一些刷新,这足以修复 PREVIOUS 分配。对 [1] 的分配被正确地视为更改,并更新当前项目。听起来像是一个微妙的错误(或动态变化的限制)。
猜你喜欢
  • 2022-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
  • 2020-04-24
  • 2019-07-08
相关资源
最近更新 更多