绑定到 ViewModel 在 Xamarin.Forms 中不起作用

Posted

技术标签:

【中文标题】绑定到 ViewModel 在 Xamarin.Forms 中不起作用【英文标题】:Binding to the ViewModel not working in Xamarin.Forms 【发布时间】:2022-01-14 03:13:51 【问题描述】:

我正在尝试制作一个显示国家列表的应用程序,当单击一个国家/地区时,它会显示该国家/地区的城市列表。

Country.cs:

public class Country 
  public string Name  get; set; 
  public ImageSource Image  get; set; 
  public IList<City> Cities  get; set; 

City.cs:

public class City

    public string Name  get; set; 

在 CountryPageViewModel.cs 中通过以下方式进行导航:

async void OnSelectedCountry(Country country)
    
        if (country == null)
        
            return;
        

        await Shell.Current.GoToAsync($"nameof(CitiesPage)?nameof(CitiesViewModel.Name)=country.Name");
    

城市被加载到 CitiesViewModel.cs 中:

[QueryProperty(nameof(Name), nameof(Name))]
public class CitiesViewModel : BaseViewModel

    private string countryName;

    public IList<City> CityList  get; set; 

    public string Name
    
        get
        
            return countryName;
        

        set
        
            countryName = value;
            LoadCities(value);
        
    

    public async void LoadCities(string countryName)
    
        try
        
            Country country = await DataStore.GetItemAsync(cityName);
            IList<City> cities = country.Cities;
            CityList = cities;
        
        catch (Exception)
        
            Console.WriteLine("Impossible to load cities");
        
    

在 XAML (CitiesPage.xaml) 中:

<CollectionView x:Name="citiesCollectionView"  x:DataType="viewmodels:CitiesViewModel"
            ItemsSource="Binding CityList"
            EmptyView="Impossible to load cities" >
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="5" x:DataType="models:City">
                <Frame Style="StaticResource CityCard">
                    <Grid RowDefinitions="Auto,Auto"
                          ColumnDefinitions="Auto" >
                        <Label Grid.Column="1" 
                            Text="Binding Name" 
                            FontAttributes="Bold"
                            VerticalTextAlignment="Center"
                            Padding="10"
                            HeightRequest="50" />
                    </Grid>
                </Frame>
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

但“城市”页面中没有显示任何内容。我已将 CitiesPage.xaml.cs(代码隐藏)中的 BindingContext 设置为 ViewModel。

我做错了什么?

【问题讨论】:

您的二传手似乎都没有致电PropertyChangedLoadCities 中的代码似乎引用了几个未定义的变量。这是剪切/粘贴错误,还是实际代码是这样的?您是否对其进行了调试以验证是否已加载数据? LoadCities 中的未定义变量是剪切/粘贴错误,因为我试图将它们翻译成英文,regione 在代码中代表 Country。我需要修改和添加哪些setter PropertyChanged 你正在绑定到CityList,所以你需要在设置时提高PropertyChanged 成功了!感谢您的宝贵时间,这真的很有帮助! 【参考方案1】:

对于可能有同样问题的人,正如 xamarin 文档所说的那样

视图可访问的所有视图模型和模型类都应该 实现 INotifyPropertyChanged 接口。实现这个 视图模型或模型类中的接口允许该类提供 更改通知到视图中的任何数据绑定控件时, 基础属性值变化。

以下是关于 PropertyChanged 的​​更多提示:

-如果公共属性的值,总是引发 PropertyChanged 事件 变化。不要假设引发 PropertyChanged 事件可以 由于了解 XAML 绑定的发生方式而被忽略。

总是为任何计算属性引发 PropertyChanged 事件,其 值被视图模型或模型中的其他属性使用。

总是在方法结束时引发 PropertyChanged 事件 属性更改,或者当已知对象处于安全状态时。 引发事件通过调用事件的 处理程序同步。如果这发生在操作过程中, 它可能会在对象处于 不安全,部分更新的状态。此外,还可以 由 PropertyChanged 事件触发的级联更改。级联 更改通常需要在级联之前完成更新 更改可以安全执行。

永远不要引发 PropertyChanged 事件,如果 属性不变。这意味着你必须比较旧的 和引发 PropertyChanged 事件之前的新值。

从不提高 如果您是视图模型的构造函数期间的 PropertyChanged 事件 初始化一个属性。视图中的数据绑定控件不会有 订阅在此时接收更改通知。

从不 引发多个具有相同属性的 PropertyChanged 事件 在公共的单个同步调用中的名称参数 一个类的方法。例如,给定一个 NumberOfItems 属性,其 后备存储是 _numberOfItems 字段,如果方法递增 _numberOfItems 在循环执行期间 50 次,它应该只在 NumberOfItems 属性上引发属性更改通知 一次,在所有工作完成之后。对于异步方法,raise 每个给定属性名称的 PropertyChanged 事件 异步延续链的同步段。

【讨论】:

以上是关于绑定到 ViewModel 在 Xamarin.Forms 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

将 CheckListBox 绑定到 ViewModel

如何绑定到CarouselView(Xamarin.Forms)(MVVM)内部的ViewModel元素?

将自定义组件存储配置绑定到 ViewModel 存储

绑定到 ViewModel 在 Xamarin.Forms 中不起作用

将 IsEnabled 绑定到父 ViewModel 而不是 UserControl ViewModel

如何将 TabControl 绑定到 ViewModel 集合?