>

Xamarin.Forms에서 크로스 플랫폼 앱을 개발 중입니다.
페이지 중 하나에 동일한 항목 목록을 가진 3 개의 피커 세트를 표시해야합니다. 아이디어는 피커 중 하나에서 항목을 선택하면 다른 두 항목의 항목 소스에서 제거된다는 것입니다.
이를 위해 다음 코드를 개발했습니다.
BaseList 라는 아이템 목록으로 시작했습니다  우리는 웹 서비스에서 얻을 수 있습니다. 또한 3 개의 개별 목록 ( ListA )을 만듭니다. ListB  그리고 ListC ) 및 각 피커의 선택된 항목 ( SelectedA )을 저장할 항목 3 개 SelectedB  그리고 SelectedC ).

private List<Item> BaseList;
private List<Item> _ListA;
private Item _SelectedA;
private List<Item> _ListB;
private Item _SelectedB;
private List<Item> _ListC;
private Item _SelectedC;
…
//Api Calls
private void LoadData()
{
         …
    BaseList = new List<Item> (ListFromWebServices);
    _ListA = new List<Item>(BaseList);
    OnPropertyChanged(nameof(ListA));
    _ListB = new List<Item>(BaseList);
    OnPropertyChanged(nameof(ListB));
    _ListC = new List<Item>(BaseList);
    OnPropertyChanged(nameof(ListC));
}
…
//Public Fields
public List<Item> ListA
{
    get
    {
        return _ListA;
    }
}
public Item SelectedA
{
    get
    {
        return _SelectedA;
    }
    set
    {
        SetProperty(ref _SelectedA, value, nameof(SelectedA));
    }
}
public List<Item> ListB
{
    get
    {
        return _ListB;
    }
}
public Item SelectedB
{
    get
    {
        return _SelectedB;
    }
    set
    {
        SetProperty(ref _SelectedB, value, nameof(SelectedB));
    }
}
public List<Item> ListC
{
    get
    {
        return _ListC;
    }
}
public Item SelectedC
{
    get
    {
        return _SelectedC;
    }
    set
    {
        SetProperty(ref _SelectedC, value, nameof(SelectedC));
    }
}

이 코드는 ViewModel에 있으므로 SetProperty를 사용하여 참조 된 속성을 값으로 설정하고 PropertyChangedEventArgs 를 호출합니다.   INotifyPropertyChanged 에서

public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value,
                              [CallerMemberName] string propertyName = null)
{
    if (Equals(storage, value))
        return false;
    storage = value;
    OnPropertyChanged(propertyName);
    return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

ItemSource를 업데이트하기 위해 선택된 항목이 변경 될 때마다 OnSelectedItemChanged 를 호출합니다   SelectedA 의 세터에서 SelectedB  그리고 SelectedC . 이 메소드는 어떤 Picker가 트리거했는지를 나타내는 색인을받습니다 :

private void OnSelectedItemChanged(int index)
{
Item CurrentA = SelectedA;
Item CurrentB = SelectedB;
Item CurrentC = SelectedC;
    int i;
    switch (index)
    {
        case 0:
            _ListB = new List<Item> (BaseList);
            _ListB.Remove(CurrentA);
            _ListB.Remove(CurrentC);
            OnPropertyChanged(nameof(ListB));
            _ListC = new List<Item>(BaseList);
            _ListC.Remove(CurrentA);
            _ListC.Remove(CurrentB);
            OnPropertyChanged(nameof(ListC));
            i = ListB.IndexOf(CurrentB);
            if (i > -1)
            {
                _SelectedB = ListB[i];
            }
            OnPropertyChanged(nameof(SelectedB));
            i = ListC.IndexOf(CurrentC);
            if (i > -1)
            {
                _SelectedC = ListC[i];
            }
            OnPropertyChanged(nameof(SelectedC));
            break; 
        case 1:
            _ListA = new List<Item>(BaseList);
            _ListA.Remove(CurrentB);
            _ListA.Remove(CurrentC);
            OnPropertyChanged(nameof(ListA));
            _ListC = new List<Item>(BaseList);
            _ListC.Remove(CurrentA);
            _ListC.Remove(CurrentB); 
            OnPropertyChanged(nameof(ListC));
            i = ListA.IndexOf(CurrentA);
            if (i > -1)
            {
                _SelectedA = ListA[i];
            }
            OnPropertyChanged(nameof(SelectedA));
            i = ListC.IndexOf(CurrentC);
            if (i > -1)
            {
                _SelectedC = ListC[i];
            }
            OnPropertyChanged(nameof(SelectedC));
            break;
         case 2:
            _ListA = new List<Item>(BaseList);
            _ListA.Remove(CurrentB);
            _ListA.Remove(CurrentC);
            OnPropertyChanged(nameof(ListA));
            _ListB = new List<Item>(BaseList);
            _ListB.Remove(CurrentA);
            _ListB.Remove(CurrentC); 
            OnPropertyChanged(nameof(ListB));
           i = ListA.IndexOf(CurrentA);
            if (i > -1)
            {
                _SelectedA = ListA[i];
            }
            OnPropertyChanged(nameof(SelectedA));
            i = ListB.IndexOf(CurrentB);
            if (i > -1)
            {
                _SelectedB = ListB[i];
            }
            OnPropertyChanged(nameof(SelectedB));
            break;
    }
}

우리가하는 일은 기본적으로 각 선택기에 대해 현재 선택된 항목을 별도의 변수에 저장하고 BaseList 를 복사하는 것입니다  이벤트를 호출하지 않은 두 개의 선택기로 들어간 다음 각 새 목록에서 다른 선택기로 사용중인 모든 옵션을 제거하고 각 새 목록에서 선택한 항목을 원래 선택한 항목으로 다시 설정하고 마지막으로 OnPropertyChanged() 를 호출하십시오.  변경 사항에 대한 정보를 제공합니다.

여기서 문제는 우리가 ItemSource 를 바꿀 때  선택기에서 SelectedItem 를 설정합니다.   null 로 . 전화 OnPropertyChanged()   OnSelectedItemChanged() 후 세터에 이 호출되면 한 피커가 다른 피커를 무한 루프로 연결하고 설정하기 전에 값이 null이 아닌지 확인하는 필터를 추가하면 피커에 선택된 항목이 표시되지 않고 값이 이미 설정되어 있습니다.

  • 답변 # 1

    누가 같은 문제를 겪을 경우를 대비하여 해결책을 찾았습니다. 당신이 CurrentA 를 만들면 밝혀 CurrentB  그리고 CurrentC  전역 변수 및 각 경우에 if ((CurrentA != SelectedA) && (!(SelectedA is null))) { ... (do all the stuff) } break; 추가  그리고 마지막에

    _SelectedA = CurrentA;
    OnPropertyChanged(nameof(SelectedA));
    _SelectedB = CurrentB;
    OnPropertyChanged(nameof(SelectedB));
    _SelectedC = CurrentC;
    OnPropertyChanged(nameof(SelectedC));
    
    

    작동합니다. 우리는 왜 tho :)

  • 이전 ecmascript 6 - es6 map과 immutablejs map 사이에 차이점이 있습니까?
  • 다음 javascript - 부모 DIV에서 클래스별로 DIV 찾기