Выбор в пользовательском контроле - PullRequest
0 голосов
/ 22 января 2019

Я создаю несколько форм (используя TableView) и заметил, что я стилизовал ячейки одинаково.Я решил, что я бы преобразовал этот повторяющийся код в общий элемент управления.

Я изо всех сил пытаюсь заставить привязку работать правильно на сборщике.Мой пользовательский элемент управления выглядит следующим образом: picture of the cell

Мой элемент управления - ViewCell, поэтому я могу отображать его в пределах TableView:

public partial class PickerCell : ViewCell
{
...
}

Мне удалось установить средства выбора ItemSource, но я не могу заставить работать свойства SelectedItem или DisplayItemBinding.

Я видел это сообщение за 2015 год (древний сейчас), но я попробовал, и методы были помечены как устаревшие и все равно не работали.

Я также пробовал в элементе управления ctor:

ItemPicker.SetBinding(Picker.ItemsSourceProperty, "ItemSource");
ItemPicker.SetBinding(Picker.SelectedItemProperty, "SelectedItem", BindingMode.TwoWay);

, но это не помоглоработать либо.

Я просто хочу добавить способ, чтобы я мог привязать к сборщику из моего xaml к элементу управления.Я действительно надеюсь, что это возможно, потому что я использую эту точную ячейку просмотра вокруг своего приложения, возможно, 9/10 раз.Я действительно не хочу повторяться много раз, и я обычно создаю элементы управления в этом сценарии.Например, у меня есть ячейка для записей в похожем стиле, и она отлично работает ...

Вот код, который я использовал для установки источника элемента:

public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
    nameof(ItemsSource),
    typeof(IList),
    typeof(PickerCell)
    propertyChanged: (bindable, oldVal, newVal) => ((PickerCell) bindable).OnItemsSourceChanged((IList) newVal)
);

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

private void OnItemsSourceChanged(IList list)
{
    ItemPicker.ItemsSource = list;
}

Я попытался реализовать некоторыекода для сборщика от Xamarin , но безрезультатно.

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 29 марта 2019

Вот реализация пользовательской ячейки выбора. Единственным изменением ванильного ксамарина является то, что отображение привязки должно вводиться как string вместо binding: property.

Вот весь важный код:

Декларации обязательного имущества

/// <summary>
/// The placeholder property.
/// </summary>
public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(
    nameof(Placeholder),
    typeof(string),
    typeof(CustomPickerCell),
    propertyChanged: (bindable, oldVal, newVal) => ((CustomPickerCell)bindable).OnPlaceholderChanged((string)newVal)
);

/// <summary>
/// The items source property.
/// </summary>
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
    nameof(ItemsSource),
    typeof(IList),
    typeof(CustomPickerCell),
    propertyChanged: (bindable, oldVal, newVal) => ((CustomPickerCell)bindable).OnItemsSourceChanged((IList)newVal)
);

/// <summary>
/// The selected item property.
/// </summary>
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(
    nameof(SelectedItem),
    typeof(object),
    typeof(CustomPickerCell),
    defaultBindingMode: BindingMode.TwoWay,
    propertyChanged: (bindable, oldVal, newVal) => ((CustomPickerCell)bindable).OnSelectedItemChanged((object)newVal)
);

/// <summary>
/// The item display binding property
/// NOTE: Use the name of the property, you do not need to bind to this property.
/// </summary>
public static readonly BindableProperty ItemDisplayBindingProperty = BindableProperty.Create(
    nameof(ItemDisplayBinding),
    typeof(string),
    typeof(CustomPickerCell),
    defaultBindingMode: BindingMode.TwoWay,
    propertyChanged: (bindable, oldVal, newVal) => ((CustomPickerCell)bindable).OnItemDisplayBindingChanged((string)newVal)
);

Свойства привязки

/// <summary>
/// The cell's placeholder (select a ....).
/// </summary>
/// <value>The placeholder.</value>
public string Placeholder
{
    get { return (string)GetValue(PlaceholderProperty); }
    set { SetValue(PlaceholderProperty, value); }
}

/// <summary>
/// The cell's picker item source.
/// </summary>
/// <value>The items source.</value>
public IList ItemsSource
{
    get { return (IList)GetValue(ItemsSourceProperty); }
    set { SetValue(ItemsSourceProperty, value); }
}

/// <summary>
/// Gets or sets the selected item.
/// </summary>
/// <value>The selected item.</value>
public object SelectedItem
{
    get { return GetValue(SelectedItemProperty); }
    set { SetValue(SelectedItemProperty, value); }
}

/// <summary>
/// Gets or sets the item display binding.
/// </summary>
/// <value>The item display binding.</value>
public string ItemDisplayBinding
{
    get { return (string)GetValue(ItemDisplayBindingProperty); }
    set { SetValue(ItemDisplayBindingProperty, value); }
}

Методы, измененные свойством

/// <summary>
/// Called when PlaceholderProperty changes.
/// </summary>
/// <param name="newVal">New value.</param>
private void OnPlaceholderChanged(string newVal)
{
    ItemPicker.Title = newVal;
}

/// <summary>
/// Called when ItemSourceProperty changes.
/// </summary>
private void OnItemsSourceChanged(IList list)
{
    ItemPicker.ItemsSource = list;
}

/// <summary>
/// Called when SelectedItemProperty changes.
/// </summary>
/// <param name="obj">Object.</param>
private void OnSelectedItemChanged(object obj)
{
    ItemPicker.SelectedItem = obj;
}

/// <summary>
/// Called when ItemDisplayBindingProperty changes.
/// </summary>
/// <param name="newvalue">Newvalue.</param>
private void OnItemDisplayBindingChanged(string newvalue)
{
    ItemPicker.ItemDisplayBinding = new Binding(newvalue);
}

* 1023 инициализации *

public CustomPickerCell()
{
    InitializeComponent();

    ItemPicker.ItemsSource = this.ItemsSource;
    ItemPicker.SelectedItem = this.SelectedItem;

    ItemPicker.SelectedIndexChanged += OnSelectedIndexChanged;
}

/// <summary>
/// Calle when ItemPicker's SelectedIndexChanged event fires.
/// </summary>
/// <param name="sender">Sender.</param>
/// <param name="e">E.</param>
void OnSelectedIndexChanged(object sender, EventArgs e)
{
    this.SelectedItem = (ItemPicker.SelectedIndex < 0 || ItemPicker.SelectedIndex > ItemPicker.Items.Count - 1) ? null : ItemsSource[ItemPicker.SelectedIndex];
}

Теперь все, что вам нужно сделать, это добавить эту ячейку в ваш xaml, и все готово!

Usage

<!-- Where controls is a namespace defined in your xaml -->
<!-- Not not to bind ItemDisplayBinding, you only need the property name as a string-->
<controls:CustomPickerCell Title="Type" Placeholder="Select an ice cream" 
                        ItemsSource="{Binding IceCreamList}" 
                        SelectedItem="{Binding SelectedIceCream, Mode=TwoWay}" 
                        ItemDisplayBinding="Name"/>
0 голосов
/ 23 января 2019

У меня была похожая ситуация для моего пользовательского средства выбора, когда я хотел реализовать обработчик событий для изменения выбранного элемента. Вот как я это сделал.

В коде вашего пользовательского средства выбора реализуйте свойство EventHandler и частную переменную:

private EventHandler onIndexChanged = null;
...
public event EventHandler OnIndexChangedEvent
{
    add
    {
        onIndexChanged = null;
        onIndexChanged = value;
    }
    remove
    {
        onIndexChanged = null;
    }
}

В XAML вашего пользовательского средства выбора добавьте обработчик к свойству SelectedIndexChanged:

<Picker
    x:Name="MyPicker"
    SelectedIndexChanged="Handle_SelectedIndexChanged"/>

Затем вернитесь в свой код и внедрите этот обработчик:

void Handle_SelectedIndexChanged(object sender, System.EventArgs e)
{
    // Trigger the implemented event, if not null.
    onIndexChanged?.Invoke(sender, e);
}

Вышеприведенное не является привязываемым, поэтому для его реализации необходимо:

  1. Установите обработчик на главном экране:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    x:Class="MyApp.MyPage"
    xmlns:controls="clr-namespace:MyApp.Controls">
    <ContentPage.Content>
        <StackLayout
            HorizontalOptions="FillAndExpand"
            VerticalOptions="FillAndExpand">
             <controls:CustomPicker
                ItemSource="{Binding SelectionList}"
                OnIndexChangedEvent="Handle_PickerIndexChangedEvent"/>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
  1. Реализуйте обработчик в коде вашего представления, чтобы вызвать обработчик модели представления:
private void Handle_PickerIndexChangedEvent(object sender, System.EventArgs e)
{
    viewModel.HandlerIndexChanged(); // or whatever
}

Возможно, есть лучшие способы сделать это, а именно реализовать Command и CommandParameter. Однако вышесказанное сработало для меня, даже если мне пришлось немного изменить правила MVVM.

...