Прокрутка в CollectionView не поддерживает выбор переключателя Switch - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть следующее CollectionView -

<CollectionView x:Name="PCollection" ItemsSource="{Binding P.data}" Margin="0,10,2,10">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <StackLayout>
                <Image Source="p" HeightRequest="60" WidthRequest="60" />
                <StackLayout Orientation="Vertical" >
                    <Label Text="{Binding id}" VerticalOptions="Center" IsVisible="False"/>
                    <StackLayout Orientation="Horizontal" >+
                    <Switch IsToggled="{Binding IsOwned, Mode=TwoWay}" HorizontalOptions="Start" Toggled="Switch_Toggled_Place" />
                </StackLayout>
            </StackLayout>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

С моим кодом позади -

bool _isOwned;
public bool IsOwned
{
    get
    {
        return _isOwned;
    }
    set
    {
        _isOwned = value;

    }
}

private void Switch_Toggled_Place(object sender, ToggledEventArgs e)
{

}

Моя проблема в том, что когда я переключаю переключатель в коллекции, все работает как ожидается, и я вступаю в Switch_Toggled_Place. Однако, скажем, в коллекции 20 предметов, когда я прокручиваю вверх и переключаемый переключатель исчезает из поля зрения, по какой-то причине он снова запускает Switch_Toggled_Place и снимает флажок с моего переключателя!

Я попытался удалить Mode=TwoWay от привязки к эффекту нет. Я также попытался установить sh, если событие переключения происходило из пользовательского ввода или из самого кода, но опять же безрезультатно. Как я могу решить эту проблему, я уверен, что это просто.

Ответы [ 2 ]

1 голос
/ 29 апреля 2020

В соответствии с этим GitHub Issue , который является предложением добавить событие OnClick к коммутатору, у людей возникла такая же проблема, как и у вас.

С учетом сказанного, как обходной путь Вы можете добавить StackLayout поверх коммутатора с помощью TapGesture для регистрации касания, а затем переключить / отменить переключение, устраняя необходимость в переключаемом событии

Пример:

<Grid>
    <Switch IsToggled="{Binding IsOwned}"></Switch>
    <StackLayout>
        <StackLayout.GestureRecognizers>
            <TapGestureRecognizer 
                Tapped="OnSwitchTapped" 
                NumberOfTapsRequired="1">
        </StackLayout.GestureRecognizers>
    </StackLayout>
</Grid>

...

public void OnSwitchTapped(object sender, EventArgs e)
{
    //Change Switch IsToggle
    //add code here
}

Это очень простой пример, но вы понимаете, что вам нужно делать. это ни в коем случае не хорошее решение, это обходной путь, способ, которым вы делали, является правильным

1 голос
/ 29 апреля 2020

Вам необходимо реализовать интерфейс INotifyPropertyChanged

в вашей модели

public partial class MyModel: INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged([CallerMemberName] string name = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

   bool _isOwned;
   public bool IsOwned
   { 
     get
     {
        return _isOwned;
     }
     set
     {
        if(_isOwned!=value)
            {
                _isOwned= value;
                OnPropertyChanged(nameof(IsOwned));

            }

      }
}


И поскольку вы использовали MVVM, вы должны обрабатывать логи c в ViewModel вместо Event , В противном случае он будет конфликтовать с привязкой данных.

в вашем ViewMNodel

public class MyViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged([CallerMemberName] string name = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    // MySource here is the ItemsSource of CollectionView
    public ObservableCollection<MyModel> MySource { get; set; }


    public MyViewModel()
    {
        MySource = new ObservableCollection<MyModel>() {

       //...
        };

        foreach(MyModel model in MySource)
        {
            model.PropertyChanged += Model_PropertyChanged;
        }

    }

    private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName== "IsOwned")
        {
          // do some thing you want here .
        }
    }
}
...