2016-09-11 12 views
1

컬렉션을 바인딩 할 수 있도록 Xamarin.Forms Picker를 확장하려고합니다. 빠른 검색 후이 페이지를 찾았습니다 : Picker Example 두 가지 좋은 예가 있습니다. 단지 &을 복사하는 것을 거부하면서 (학습 목적으로) 코드를 붙여 넣었습니다. 두 가지 예를 바탕으로 직접 작성했습니다.BindableProperty : 형식이 일치하지 않습니다.

광산이 작동하지 않는다면 거의 동일합니다.

ItemsSource에 컬렉션을 제공하지 않으면 모든 것이 정상적으로 작동합니다.

Xamarin.Forms.Xaml.XamlParseException: Position 9:32. Cannot assign property "ItemsSource": type mismatch between "Xamarin.Forms.Binding" and "System.Collections.IEnumerable"

선택기 :

public class BindablePicker : Picker 
{ 
    private static readonly BindableProperty ItemsSourceProperty = 
     BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged); 

    private static readonly BindableProperty SelectedItemProperty = 
     BindableProperty.Create("SelectedItem", typeof(object), typeof(BindablePicker)); 

    public IEnumerable ItemsSource 
    { 
     get { return (IEnumerable)GetValue(ItemsSourceProperty); } 
     set { SetValue(ItemsSourceProperty, value); } 
    } 
    public object SelectedItem 
    { 
     get { return GetValue(SelectedItemProperty); } 
     set { SetValue(SelectedItemProperty, value); } 
    } 
    public string DisplayMember { get; set; } 


    private static void OnItemsSourceChanged(BindableObject bindable, Object oldValue, Object newValue) 
    { 
     var newval = newValue as IEnumerable; //Had to implement this because of the non-generic .Create() method expects Object as param. 
     var picker = bindable as BindablePicker; 

     if (picker != null) 
     { 
      picker.Items.Clear(); 
      if (newval == null) return; 

      foreach (var item in newval) 
      { 
       if (string.IsNullOrEmpty(picker.DisplayMember)) 
       { 
        picker.Items.Add(item.ToString()); 
       } 
       else 
       { 
        var prop = item.GetType() 
         .GetRuntimeProperties() 
         .FirstOrDefault(p => string.Equals(p.Name, picker.DisplayMember, StringComparison.OrdinalIgnoreCase)); 

        picker.Items.Add(prop.GetValue(item).ToString()); 
       } 
      } 
     } 
    } 

    private void OnSelectedIndexChanged(object sender, EventArgs args) 
    { 
     if (SelectedIndex < 0 || SelectedIndex > Items.Count - 1) 
     { 
      SelectedItem = null; 
     } 
     else 
     { 
      SelectedItem = ItemsSource.ItemOf(SelectedIndex); //ItemOf is an extension method I made for IEnumerable (has to be tested). 
     } 
    } 
} 

뷰 모델 (부품) :

public class HomePageViewModel : ViewModelBase 
{ 
    //In the app this is populated with a List<Person>. 
    public IEnumerable<Person> People { get; set; } 
} 

XAML :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
     xmlns:controls="clr-namespace:TestApp.Controls;assembly=TestApp" 
     x:Class="TestApp.Views.HomePage"> 
    <ContentPage.Content> 
    <StackLayout> 

     <controls:BindablePicker ItemsSource="{Binding People}" 
            HorizontalOptions="Center" /> 
    </StackLayout> 
    </ContentPage.Content> 
</ContentPage> 

주 나는 다음과 같은 오류가 모음을 할당 할 때마다 lin에서 첫 번째 예제 선택기 ked 페이지는 제공된 VM/View 설정과 함께 작동합니다.

필자도 아직 끝나지 않았습니다. 여전히 SelectedItem 속성에 TwoWay 바인딩을 제공하고 ObservableCollection을 지원하려고합니다.

네,

답변

1

처음에 나는 미친 듯이 생각했습니다.

그런데 무언가가 심각하게 부서 졌다고 생각했습니다. 같은 BindableProperty를 볼 수있는 XAML 파서 위해서는

그러나 결국 나는 그것을 알아 냈 ...

private static readonly BindableProperty ItemsSourceProperty = 
    BindableProperty.Create("ItemsSource", typeof(IEnumerable), 
    typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged); 

, 그것은 public 수있다 (그리고 static,하지만 당신은 바로 그 부분을 가지고).

귀하의 경우에는

는 속성에 폴백 있도록 XAML 파서는 BindableProperty 표시되지 않지만,이 Binding을 설정할 수있는 방법을 가지고 있지 않으며, 유형으로 일치하지 않는, 당신이 얻을 예외.

public static readonly BindableProperty ItemsSourceProperty = 
    BindableProperty.Create("ItemsSource", typeof(IEnumerable), 
    typeof(BindablePicker), null, propertyChanged: OnItemsSourceChanged); 
에 코드를 변경