在ListView中一次只打开一个开关

时间:2017-06-19 11:44:07

标签: listview mvvm binding xamarin.forms

我正在尝试实现一项功能,如果我打开ListView中的任何开关,其他开关应该关闭。

以下是我的XAML:

<ListView ItemsSource="{Binding AllProfiles}" HasUnevenRows="True" SeparatorVisibility="None" RowHeight="-1">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout Orientation="Vertical" BackgroundColor="#F6F6F6">
                    <Frame Padding="2" BackgroundColor="#FFFFFF" Margin="10,5,10,5">
                        <StackLayout Orientation="Horizontal" BackgroundColor="#FFFFFF" Padding="20">
                            <StackLayout Orientation="Vertical">
                                <Label Text="{Binding Name}" TextColor="#FF6D9D" FontSize="25"></Label>
                                <Label Text="{Binding Email}" TextColor="#B1B1B1" FontSize="18"></Label>
                            </StackLayout>
                            <Switch HorizontalOptions="EndAndExpand" VerticalOptions="CenterAndExpand" IsToggled="{Binding IsActive}">
                            </Switch>
                        </StackLayout>
                    </Frame>
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

我正在使用MVVM绑定并尝试更改事件上的数据&#39; OnPropertyChanged(&#34; IsActive&#34;)&#39;但无法实施。

任何建议都会有所帮助。

修改

public class SetProfileViewModel:ViewModelBase
{        
    private ObservableCollection<Profile> _allProfiles = new ObservableCollection<Profile>();  

    public ObservableCollection<Profile> AllProfiles
    {
        get { return _allProfiles; }
        set
        {
            _allProfiles = value;
            OnPropertyChanged("AllProfiles");
        }
    }
}

public class Profile:ViewModelBase
{
    private string _name;
    private string _email;
    private bool _isActive;
    public string Name {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged("Name");
        }
    }
    public string Email
    {
        get { return _email; }
        set
        {
            _email = value;
            OnPropertyChanged("Email");
        }
    }
    public bool IsActive
    {
        get { return _isActive; }
        set
        {

            _isActive = value;                
            OnPropertyChanged("IsActive");
            //How can I change 'AllProfiles' data from here.
        }
    }
}

1 个答案:

答案 0 :(得分:1)

要从AllProfiles中的属性设置器访问ProfileItem,您需要将ProfileItem的引用添加到ViewModel,这在关注点分离方面不是一个好主意。我的建议是让ViewModel处理活动配置文件的更改。

为此,您需要将ViewModel订阅到每个项目的PropertyChanged,并相应地处理IsActive的更改。这有点痛苦,因为您需要最初订阅每个项目,取消订阅是否删除了ProfileItem并订阅了在初始化VM后添加的新项目。

然而,根据我的经验,这种样板文件对于MVVM来说很常见。一般模式是:

public class MyViewModel : INotifyPropertyChanged
{
    private bool _handleItemChanges = true;

    public ObservableCollection<ItemViewModel> Items { get; }

    public MyViewModel()
    {
        Items = new ObservableCollection<ItemViewModel>();
        Items.CollectionChanged += ItemsChanged;        
    }

    public void ItemsChanged(object s, CollectionChangedEventArgs a)
    {
        if (a.NewItems != null)
            foreach(var i in a.NewItems.OfType<ItemViewModel>)
                Register(i);

        // Handle old items accordingly with Release(i)
        // Handle collection reset
    }

    public void Register(ItemViewModel i)
    {
        i.PropertyChanged += ItemChanged;
    }

    public void Release(ItemViewModel i)
    {
        i.PropertyChanged -= ItemChanged;
    }

    private void ItemChanged(object s, PropertyChangedEventArgs a)
    {
        if (!_handleItemChanges) return;
        _handleItemChanges = false;

        if (a.PropertyName == "IsActive")
             // Handle the change

        _handleItemChanges = true;
    }
}