Привязка пользовательского элемента управления Xamarin Forms внутри ListView - PullRequest
0 голосов
/ 07 мая 2018

Сценарий - существует ListView, связанный с ObservableCollection строки. Listview имеет одну метку и один UserControl (не содержащий ничего, кроме метки). Оба привязаны к одной коллекции.

Также есть кнопка, которая генерирует случайные данные для коллекции.

Проблема в том, что когда я запускаю приложение и нажимаю кнопку «Создать данные», ярлык обновляется, но не пользовательский контроль.

Ниже приведен пример кода.

MainPage.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:TestSample"
         xmlns:controls="clr-namespace:TestSample.Controls"
         x:Class="TestSample.MainPage">

<StackLayout>
    <Button Text="Generate Data" Clicked="Button_Clicked"/>

    <ListView Grid.Row="1" HorizontalOptions="Center" ItemsSource="{Binding Collection}" SeparatorVisibility="None">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Horizontal" HorizontalOptions="Center">
                        <Label Text="{Binding}"/>
                        <Label Text=" - "/>
                        <controls:MagicBox Text="{Binding}"/>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

MainPage.xaml.cs

 public partial class MainPage : ContentPage
{
    public ObservableCollection<string> Collection { get; set; }

    public MainPage()
    {
        InitializeComponent();
        Collection = new ObservableCollection<string>
        {
            "XX",
            "XX",
            "XX"
        };

        this.BindingContext = this;
    }

    public void Button_Clicked(object sender, EventArgs e)
    {
        var rand = new Random();
        for (int i = 0; i < 3; i++)
        {
            Collection[i] = rand.Next(10, 100).ToString();
        }
    }
}

UserControl

  <ContentView.Content>
  <Grid>
      <Label Text="{Binding Text}" />
  </Grid>

public partial class MagicBox : ContentView
{

    public static readonly BindableProperty TextProperty =
      BindableProperty.Create("Text", typeof(string), typeof(MagicBox), "XX");

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public MagicBox ()
    {
        InitializeComponent ();
        this.BindingContext = this;
    }
}

Я также попытался с ObservableCollection класса POCO вместо строки после реализации INotifyPropertyChanged, не сработало. Если я связываю текст MagicBox со строкой напрямую, это работает, но не тогда, когда я связываю его с каким-либо свойством.

Ответы [ 3 ]

0 голосов
/ 07 мая 2018

Сначала обновите свой пользовательский элемент управления:

  • Измените определение свойства зависимости «Текст» => Установите режим привязки «OneWay» и добавьте обработчик события propertyChanged следующим образом:

    public partial class MagicBox : ContentView
    {
    
    public static readonly BindableProperty TextProperty =
      BindableProperty.Create("Text", typeof(TextVM), typeof(MagicBox), "XX", BindingMode.OneWay, null, new BindableProperty.BindingPropertyChangedDelegate(TextPropertyChanged));
    
    public TextVM Text
    {
        get { return (TextVM)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    
  • Затем добавьте метод 'Text' propertyChanged в свой пользовательский элемент управления следующим образом:

    private static void TextPropertyChanged(BindableObject sender, object oldValue, object newValue )
    {
        Label updatedLabel = sender as Label;
        if(updatedLabel == null) return;
    
        updatedLabel.Text = (newValue as TextVM)?.MyText;
    }
    

Создайте объект Observable, который встраивает свойство text, чтобы вызвать событие PropertyChanged:

public class TextVM : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _myText;
    public string MyText
    {
        get => _myText;
        set
        {
            _myText = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MyText"));
        }
    }
}

Затем в вашем XAML обновите текстовую привязку:

<controls:MagicBox Text="{Binding MyText}"/>

Не забудьте обновить тип коллекции и процесс генерации случайных чисел ...

Это должно быть хорошо!

0 голосов
/ 16 мая 2018

делает

this.BindingContext = this;

в MagicBox.xaml.cs принудительно устанавливает BindingContext для текущего объекта. Это также означает, что BindingContext от родителя больше не наследуется.

, чтобы заставить это работать, измените свой код на

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MagicBox : ContentView
{

    public static readonly BindableProperty TextProperty =
        BindableProperty.Create("Text", typeof(string), typeof(MagicBox), default(string));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public MagicBox ()
    {
        InitializeComponent ();
    }
}

и ваш xaml до

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="TestSample.Controls.MagicBox"
         x:Name="box">
  <ContentView.Content>
    <Grid>
        <Label Text="{Binding Text, Source={x:Reference box}}" />
    </Grid>
  </ContentView.Content>
</ContentView>

Я проверял это. это работает.

0 голосов
/ 07 мая 2018

Я думаю, что проблема в строке "this.BindingContext = this;" в вашем пользовательском контроле.

Вы должны связать так: Text = "{Binding Path = BindingContext, Source = {x: Ссылка ListViewName}}"

Убедитесь, что добавили x: Name к вашему Listview. Не проверено, но надеюсь, что оно вам поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...