Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在ListView中一次只打开一个开关_Listview_Mvvm_Binding_Xamarin.forms - Fatal编程技术网

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

在ListView中一次只打开一个开关,listview,mvvm,binding,xamarin.forms,Listview,Mvvm,Binding,Xamarin.forms,我正在尝试实现一种功能,如果我打开ListView中的任何开关,其他开关都应该关闭 以下是我的XAML: <ListView ItemsSource="{Binding AllProfiles}" HasUnevenRows="True" SeparatorVisibility="None" RowHeight="-1"> <ListView.ItemTemplate> <DataTemplate> <Vi

我正在尝试实现一种功能,如果我打开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绑定并尝试更改事件“OnPropertyChanged”(“IsActive”)上的数据,但无法实现

任何建议都会有帮助

编辑:

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.
        }
    }
}
公共类SetProfileViewModel:ViewModelBase
{        
私有ObservableCollection _allProfiles=新ObservableCollection();
公共可观察收集所有配置文件
{
获取{return\u allProfiles;}
设置
{
_所有配置文件=值;
OnPropertyChanged(“所有配置文件”);
}
}
}
公共类配置文件:ViewModelBase
{
私有字符串\u名称;
私人字符串\u电子邮件;
私人楼宇是活跃的;
公共字符串名{
获取{return\u name;}
设置
{
_名称=值;
不动产变更(“名称”);
}
}
公共字符串电子邮件
{
获取{return\u email;}
设置
{
_电子邮件=价值;
OnPropertyChanged(“电子邮件”);
}
}
公共福利活动
{
获取{return\u isActive;}
设置
{
_i活跃=价值;
不动产变更(“不动产”);
//如何从这里更改“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;
    }
}
公共类MyViewModel:INotifyPropertyChanged
{
私有bool_handleItemChanges=true;
公共可观察集合项{get;}
公共MyViewModel()
{
Items=新的ObservableCollection();
Items.CollectionChanged+=ItemsChanged;
}
公共无效项更改(对象s、集合ChangedEventArgs a)
{
如果(a.NewItems!=null)
foreach(a.NewItems.OfType中的变量i)
登记册(i);
//根据放行单(i)处理旧项目
//句柄集合重置
}
公共无效登记簿(ItemViewModel i)
{
i、 PropertyChanged+=ItemChanged;
}
公共作废发布(ItemViewModel i)
{
i、 PropertyChanged-=ItemChanged;
}
私有无效项已更改(对象s、PropertyChangedEventArgs a)
{
如果(!\u handleItemChanges)返回;
_handleItemChanges=false;
如果(a.PropertyName==“IsActive”)
//处理变化
_handleItemChanges=true;
}
}

如果您使用的是数据绑定,您只需在
AllProfiles
集合中的项上迭代,并将属性设置为false。@GeraldVersluis。。谢谢你的回复。我做了一些改变。请参阅编辑。我正在尝试更改Profile类下“IsActive”中“AllProfiles”的项目数据。我该怎么做?谢谢@Marc。。你的解决方案奏效了。但是,我在这里面临着一个障碍。每次我在'ItemChanged'函数中更改属性值时,它都会根据更改的值的数量一次又一次地被调用。我尝试在更改之前释放,然后注册,但结果相同。请建议任何解决方法。@AkshatAgarwal我通常使用激活/停用处理的标志变量来避免此类循环。我已经更新了答案中的代码。希望这有帮助。