2017-03-29 17 views
1

我對C#很新,我試圖用Xamarin形式創建應用程序。我想要一個選擇器,可以從中選擇($,£等)值。請記住,我正在使用SQLite.net。所以,爲了學習如何製作應用程序,我使用了github中的一個示例。沒有爲bindablepicker長碼:C#,如何讓可綁定的字符串選擇器?

using System; 
using System.Collections; 
using System.Collections.Specialized; 
using System.Reflection; 
using Xamarin.Forms; 

namespace TodoScheduler.Controls 
{ 
    public class BindablePicker : Picker 
    { 
     bool _disableNestedCalls; 

     public static readonly BindableProperty PickerTitleProperty = 
      BindableProperty.Create("PickerTitle", typeof(string), typeof(BindablePicker), 
       null); 

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

     public static readonly BindableProperty SelectedItemProperty = 
      BindableProperty.Create("SelectedItem", typeof(Object), typeof(BindablePicker), 
       null, BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged); 

     public static readonly BindableProperty SelectedValueProperty = 
      BindableProperty.Create("SelectedValue", typeof(Object), typeof(BindablePicker), 
       null, BindingMode.TwoWay, propertyChanged: OnSelectedValueChanged); 

     public String DisplayMemberPath { get; set; } 

     public string PickerTitle 
     { 
      get { return (string)GetValue(PickerTitleProperty); } 
      set { SetValue(PickerTitleProperty, value); } 
     } 

     public IEnumerable ItemsSource 
     { 
      get { return (IEnumerable)GetValue(ItemsSourceProperty); } 
      set { SetValue(ItemsSourceProperty, value); } 
     } 

     public object SelectedItem 
     { 
      get { return GetValue(SelectedItemProperty); } 
      set 
      { 
       if (this.SelectedItem != value) 
       { 
        SetValue(SelectedItemProperty, value); 
        InternalSelectedItemChanged(); 
       } 
      } 
     } 

     public object SelectedValue 
     { 
      get { return GetValue(SelectedValueProperty); } 
      set 
      { 
       SetValue(SelectedValueProperty, value); 
       InternalSelectedValueChanged(); 
      } 
     } 

     public string SelectedValuePath { get; set; } 

     public BindablePicker() 
     { 
      this.SelectedIndexChanged += OnSelectedIndexChanged; 
     } 

     public event EventHandler<SelectedItemChangedEventArgs> ItemSelected; 

     void InstanceOnItemsSourceChanged(Object oldValue, Object newValue) 
     { 
      _disableNestedCalls = true; 

      this.Items.Clear(); 
      var oldCollectionINotifyCollectionChanged = oldValue as INotifyCollectionChanged; 
      if (oldCollectionINotifyCollectionChanged != null) 
      { 
       oldCollectionINotifyCollectionChanged.CollectionChanged -= ItemsSource_CollectionChanged; 
      } 
      var newCollectionINotifyCollectionChanged = newValue as INotifyCollectionChanged; 
      if (newCollectionINotifyCollectionChanged != null) 
      { 
       newCollectionINotifyCollectionChanged.CollectionChanged += ItemsSource_CollectionChanged; 
      } 
      if (!Equals(newValue, null)) 
      { 
       var hasDisplayMemberPath = !String.IsNullOrWhiteSpace(this.DisplayMemberPath); 
       foreach (var item in (IEnumerable)newValue) 
       { 
        if (hasDisplayMemberPath) 
        { 
         var type = item.GetType(); 
         var prop = type.GetRuntimeProperty(this.DisplayMemberPath); 
         this.Items.Add(prop.GetValue(item).ToString()); 
        } 
        else 
        { 
         this.Items.Add(item.ToString()); 
        } 
       } 

       this.SelectedIndex = -1; // select first item by default 
       this._disableNestedCalls = false; 

       if (this.SelectedItem != null) 
       { 
        this.InternalSelectedItemChanged(); 
       } 
       else if (hasDisplayMemberPath && this.SelectedValue != null) 
       { 
        this.InternalSelectedValueChanged(); 
       } 
      } 
      else 
      { 
       _disableNestedCalls = true; 
       this.SelectedIndex = -1; 
       this.SelectedItem = null; 
       this.SelectedValue = null; 
       _disableNestedCalls = false; 
      } 
     } 

     void InternalSelectedItemChanged() 
     { 
      if (_disableNestedCalls) 
      { 
       return; 
      } 

      var selectedIndex = -1; 
      Object selectedValue = null; 

      if (this.ItemsSource != null) 
      { 
       var index = 0; 

       var hasSelectedValuePath = !String.IsNullOrWhiteSpace(this.SelectedValuePath); 

       foreach (var item in ItemsSource) 
       { 
        if (item != null && item.Equals(this.SelectedItem)) 
        { 
         selectedIndex = index; 
         if (hasSelectedValuePath) 
         { 
          var type = item.GetType(); 
          var prop = type.GetRuntimeProperty(this.SelectedValuePath); 
          selectedValue = prop.GetValue(item); 
         } 
         break; 
        } 
        index++; 
       } 
      } 
      _disableNestedCalls = true; 
      this.SelectedValue = selectedValue; 
      this.SelectedIndex = selectedIndex;   
      _disableNestedCalls = false; 
     } 

     void InternalSelectedValueChanged() 
     { 
      if (_disableNestedCalls) 
      { 
       return; 
      } 

      if (String.IsNullOrWhiteSpace(this.SelectedValuePath)) 
      { 
       return; 
      } 

      var selectedIndex = -1; 

      Object selectedItem = null; 

      var hasSelectedValuePath = !String.IsNullOrWhiteSpace(this.SelectedValuePath); 

      if (this.ItemsSource != null && hasSelectedValuePath) 
      { 
       var index = 0; 

       foreach (var item in ItemsSource) 
       { 
        if (item != null) 
        { 
         var type = item.GetType(); 
         var prop = type.GetRuntimeProperty(this.SelectedValuePath); 
         if (Object.Equals(prop.GetValue(item), this.SelectedValue)) 
         { 
          selectedIndex = index; 
          selectedItem = item; 
          break; 
         } 
        } 
        index++; 
       } 
      } 
      _disableNestedCalls = true; 
      this.SelectedItem = selectedItem; 
      this.SelectedIndex = selectedIndex; 
      _disableNestedCalls = false; 
     } 

     void ItemsSource_CollectionChanged(Object sender, NotifyCollectionChangedEventArgs e) 
     { 
      var hasDisplayMemberPath = !String.IsNullOrWhiteSpace(this.DisplayMemberPath); 
      if (e.Action == NotifyCollectionChangedAction.Add) 
      { 
       foreach (var item in e.NewItems) 
       { 
        if (hasDisplayMemberPath) 
        { 
         var type = item.GetType(); 
         var prop = type.GetRuntimeProperty(this.DisplayMemberPath); 
         this.Items.Add(prop.GetValue(item).ToString()); 
        } 
        else 
        { 
         this.Items.Add(item.ToString()); 
        } 
       } 
      } 
      else if (e.Action == NotifyCollectionChangedAction.Remove) 
      { 
       foreach (var item in e.NewItems) 
       { 
        if (hasDisplayMemberPath) 
        { 
         var type = item.GetType(); 
         var prop = type.GetRuntimeProperty(this.DisplayMemberPath); 
         this.Items.Remove(prop.GetValue(item).ToString()); 
        } 
        else 
        { 
         this.Items.Remove(item.ToString()); 
        } 
       } 
      } 
      else if (e.Action == NotifyCollectionChangedAction.Replace) 
      { 
       foreach (var item in e.NewItems) 
       { 
        if (hasDisplayMemberPath) 
        { 
         var type = item.GetType(); 
         var prop = type.GetRuntimeProperty(this.DisplayMemberPath); 
         this.Items.Remove(prop.GetValue(item).ToString()); 
        } 
        else 
        { 
         var index = this.Items.IndexOf(item.ToString()); 
         if (index > -1) 
         { 
          this.Items[index] = item.ToString(); 
         } 
        } 
       } 
      } 
      else if (e.Action == NotifyCollectionChangedAction.Reset) 
      { 
       this.Items.Clear(); 

       if (e.NewItems != null) 
       { 
        foreach (var item in e.NewItems) 
        { 
         if (hasDisplayMemberPath) 
         { 
          var type = item.GetType(); 
          var prop = type.GetRuntimeProperty(this.DisplayMemberPath); 
          this.Items.Remove(prop.GetValue(item).ToString()); 
         } 
         else 
         { 
          var index = this.Items.IndexOf(item.ToString()); 
          if (index > -1) 
          { 
           this.Items[index] = item.ToString(); 
          } 
         } 
        } 
       } 
       else 
       { 
        _disableNestedCalls = true; 
        this.SelectedItem = null; 
        this.SelectedIndex = -1; 
        this.SelectedValue = null; 
        _disableNestedCalls = false; 

       } 
      } 
     } 

     static void OnItemsSourceChanged(BindableObject bindable, Object oldValue, Object newValue) 
     { 
      if (Equals(newValue, null) && Equals(oldValue, null)) 
      { 
       return; 
      } 

      var picker = (BindablePicker)bindable; 
      picker.InstanceOnItemsSourceChanged(oldValue, newValue); 
     } 

     void OnSelectedIndexChanged(Object sender, EventArgs e) 
     { 
      if (_disableNestedCalls) 
      { 
       return; 
      } 

      if (this.SelectedIndex < 0 || this.ItemsSource == null || !this.ItemsSource.GetEnumerator().MoveNext()) 
      { 
       _disableNestedCalls = true; 

       if (this.SelectedIndex != -1) 
       { 
        //this.SelectedIndex = -1; 
        this.SelectedIndex = 0; 
       } 

       this.SelectedItem = null; 
       this.SelectedValue = null; 
       _disableNestedCalls = false; 
       return; 
      } 

      _disableNestedCalls = true; 

      var index = 0; 
      var hasSelectedValuePath = !String.IsNullOrWhiteSpace(this.SelectedValuePath); 

      foreach (var item in ItemsSource) 
      { 
       if (index == this.SelectedIndex) 
       { 
        this.SelectedItem = item; 

        if (hasSelectedValuePath) 
        { 
         var type = item.GetType(); 
         var prop = type.GetRuntimeProperty(this.SelectedValuePath); 
         this.SelectedValue = prop.GetValue(item); 
        } 

        break; 
       } 
       index++; 
      } 

      _disableNestedCalls = false; 
     } 

     static void OnSelectedItemChanged(BindableObject bindable, Object oldValue, Object newValue) 
     { 
      var boundPicker = (BindablePicker)bindable; 
      boundPicker.ItemSelected?.Invoke(boundPicker, new SelectedItemChangedEventArgs(newValue)); 
      boundPicker.InternalSelectedItemChanged(); 
     } 

     static void OnSelectedValueChanged(BindableObject bindable, Object oldValue, Object newValue) 
     { 
      var boundPicker = (BindablePicker)bindable; 
      boundPicker.InternalSelectedValueChanged(); 
     } 
    } 
} 

形式代碼:

  <controls:BindablePicker Margin="20,5" 
                     ItemsSource="{Binding PriorityList}" 
           SelectedItem="{Binding Priority, Mode=TwoWay}" 
           DisplayMemberPath="Title" 
           Title="Choose" 
           VerticalOptions="EndAndExpand"/> 

型號:

TodoPriority _priority = TodoPriority.Low; 
    [NotNull] public TodoPriority Priority { 
     get { return _priority; } 
     set { SetProperty(ref _priority, value); } 
    } 

視圖模型:

TodoPriority _priority = TodoPriority.Low; 
    public TodoPriority Priority 
    { 
     get { return _priority; } 
     set { SetProperty(ref _priority, value); } 
    } 

    IEnumerable<TodoPriority> _priorityList = Enum.GetValues(typeof(TodoPriority)).Cast<TodoPriority>(); 
    public IEnumerable<TodoPriority> PriorityList 
    { 
     get { return _priorityList; } 
     set { SetProperty(ref _priorityList, value); } 
    } 

TodoPriority:

namespace TodoScheduler.Enums 
{ 
    public enum TodoPriority 
    { 
     Low = 0, 
     Normal, 
     High 
    } 
} 

目前我可以從picker(low,normal,high)中進行選擇,但是我該如何改變呢?我知道我不能將這些值從Todopriority更改爲貨幣令牌,因爲它的枚舉。我試圖讓他們成爲所有的字符串,但後來我發現了一個問題,即我如何能夠創造這些價值。我知道它有點愚蠢的問題,但我已經搜索了很多,並且不能把它弄明白。

+1

XF現在有一個內置可綁定選擇器:https://blog.xamarin.com/new-bindable-picker-control-for-xamarin-forms/ – Jason

回答

0

你可以嘗試創建一個類來表示每個挑選項目

class PriorityPickerValue { 

    public string Title { get; set; } 
    public TodoPriority Priority { get; set; } 

} 

這樣,你可以指定你的價值觀如何看待在選擇器,仍然可以訪問TodoPriority財產