【问题标题】:Two way binding with ObservableCollection<string> in Xamarin Forms在 Xamarin Forms 中使用 ObservableCollection<string> 的两种方式绑定
【发布时间】:2020-11-21 07:36:14
【问题描述】:

我正在使用可绑定的StackLayout 来显示一系列绑定到ObservableCollection&lt;string&gt;Entry(视图模型中的Addresses 向下)。

在 UI 上显示集合的内容不是问题,但如果我修改任何 Entry 的内容,它不会反映在原始 ObservableCollection

这是视图模型:

public class MainViewModel
    {
        public ObservableCollection<string> Addresses { get; set; }
        public ICommand AddCommand { get; private set; }

        public MainViewModel()
        {
            AddCommand = new Command(AddEmail);
            Addresses = new ObservableCollection<string>();
            Addresses.Add("test1");
            Addresses.Add("test2");
        }

        void Add()
        {
            AddCommand(string.Empty);
        }
    }

这是视图:

<?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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="TestList.MainPage"
             x:Name="page">
    <StackLayout>

        <StackLayout Orientation="Horizontal">
            <Label Text="Addresses"
                       FontSize="Large"
                       HorizontalOptions="FillAndExpand"
                       VerticalOptions="Center"/>
            <Button Command="{Binding AddCommand}"
                    Text="+" FontSize="Title"
                        VerticalOptions="Center"/>
        </StackLayout>

        <StackLayout BindableLayout.ItemsSource="{Binding Addresses}">
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                    <StackLayout Orientation="Horizontal">
                        <Entry Text="{Binding ., Mode=TwoWay}" HorizontalOptions="FillAndExpand"/>
                        <Button Text="-" FontSize="Title""/>
                    </StackLayout>
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </StackLayout>
    </StackLayout>
</ContentPage>

我怀疑这是因为我正在处理字符串,因此无法就地修改它们。您对如何在不引入包装类或类似类的情况下解决此问题有什么建议吗?

【问题讨论】:

    标签: xaml xamarin mvvm xamarin.forms


    【解决方案1】:

    如果你想通过编辑Entry中的文本来改变后面代码中source的值。你需要在ObservableCollection类中实现接口INotifyPropertyChanged

    定义一个模型类

    public  class MyModel: INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
    
    
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
    
            string content;
    
            public string Content
            {
    
                get
                {
                    return content;
                }
    
                set
                {
                    if (content != value)
                    {
                        content = value;
                        OnPropertyChanged("Content");
                    }
                }
            }
    
        }
    

    在视图模型中

    public ObservableCollection<MyModel> Addresses { get; set; }
    
    Addresses = new ObservableCollection<MyModel>();
    Addresses.Add(new MyModel() {Content = "test1" });
    Addresses.Add(new MyModel() { Content = "test2" });
    

    在xml中

    <Entry Text="{Binding Content, Mode=TwoWay}"  HorizontalOptions="FillAndExpand"/>
    

    【讨论】:

    • 是的,我也是这么想的。但是您可以看到,这是围绕字符串创建一个包装类,以便进行双向绑定,而且它绝对是一个仅用于这种非常特殊情况的类。这就是为什么我希望在不创建另一个类的情况下使用另一种方法来实现相同的结果。
    • 我认为这是运行时唯一的方法或最简单的方法。
    【解决方案2】:

    你真的需要一个包装类才能工作,如果语法太长你可以安装PropertyCHanged.Fody包 然后你需要做的就是添加这个标签:

      [AddINotifyPropertyChangedInterface]
    public class MainViewModel
    {
        public List<Address> Addresses { get; set; }
    

    在包装类中:

      [AddINotifyPropertyChangedInterface]
    public class Address
    {
        public string Street { get; set; }
    

    【讨论】:

    • 感谢您的建议。实际上,在这种情况下困扰我的不是需要实现 INotifyPropertyChanged,而是我需要创建一个包装类:)
    • 我曾经也对此感到恼火,但只要去做就行了:)。
    猜你喜欢
    • 2017-08-28
    • 2020-11-12
    • 2018-09-15
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    相关资源
    最近更新 更多