Как мы можем связать ширину сетки, которая является элементом списка, со свойством в модели общего вида в формах xamarin? - PullRequest
1 голос
/ 17 октября 2019

У меня есть GridViewCard, которая используется в качестве шаблона данных на нескольких экранах в моем приложении форм Xamarin. И все эти страницы имеют модель представления, которая расширяется от модели базового представления. Будет ли возможно иметь ширину привязки GridCard к свойству GridLength в модели базового представления без какой-либо зависимости от страницы / списка, в котором она используется?

GridViewCard:

<Grid xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms" xmlns:i18n="clr-namespace:ScholarApp.Assets.Extensions;assembly=ScholarApp" xmlns:controls="clr-namespace:ScholarApp.Assets.Controls" xmlns:Pancake="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView" xmlns:converters="clr-namespace:ScholarApp.Assets.Converters" x:Class="ScholarApp.Assets.Templates.GridViewCard" RowSpacing="10" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Padding="{OnIdiom Phone='20,10,0,20',Tablet='30,15,0,30'}">
    <Grid.RowDefinitions>
        <RowDefinition Height="{OnIdiom Phone='200',Tablet='280'}" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="{"**this value should be dynamically bound to the page in which it is being used**" }" />
    </Grid.ColumnDefinitions>

</Grid>

Несколько вариантов использования на нескольких страницах

фрагмент кода с одной страницы:

<StackLayout Style="{DynamicResource Default}" Padding="0,5,0,0" IsVisible="{Binding IsViewVisible}">
                <flv:FlowListView x:Name="ExploreGridView" IsVisible="{Binding IsGridLayout}" BackgroundColor="Transparent" Margin="{OnIdiom Phone='0,0,20,0',Tablet='0,0,30,0'}" FlowColumnCount="{OnIdiom Phone='2',Tablet='3'}" SeparatorVisibility="None" HasUnevenRows="true" FlowItemsSource="{Binding HandpickedList}" VerticalScrollBarVisibility="Never">
                    <flv:FlowListView.FlowColumnTemplate>
                        <DataTemplate>
                            <templates:GridViewCard />
                        </DataTemplate>
                    </flv:FlowListView.FlowColumnTemplate>
                </flv:FlowListView>
            </StackLayout>

фрагмент кода с другой страницы:

<ScrollView VerticalScrollBarVisibility="Never"
                HorizontalScrollBarVisibility="Never"
                Orientation="Horizontal">
        <StackLayout Padding="{DynamicResource ExploreStkPadding20}"
                     Orientation="Horizontal"
                     Spacing="{OnIdiom Phone='20',Tablet='30'}"
                     HeightRequest="{DynamicResource HandpickedHeight}"
                     BindableLayout.ItemsSource="{Binding ViewData}">
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                    <templates:GridViewCard />
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </StackLayout>
    </ScrollView>

1 Ответ

1 голос
/ 18 октября 2019

Для этого вам понадобится пара вещей:

Сначала добавьте имя (x:Name) к Grid в GridViewCard XAML-файле. Вы будете использовать его позже.

<Grid xmlns="http://xamarin.com/schemas/2014/forms"
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"    
      x:Class="SQDictionary.GridViewCard"
      RowSpacing="10"
      x:Name="LeGrid"
      HorizontalOptions="FillAndExpand"
      BackgroundColor="BlueViolet"
      VerticalOptions="FillAndExpand"
      Padding="{OnIdiom Phone='20,10,0,20',Tablet='30,15,0,30'}">

2: Добавьте BindableProperty в ваш GridViewCard файл класса GridViewCard.cs .

public static readonly BindableProperty GridWidthProperty =
        BindableProperty.Create(nameof(GridWidth),
                                typeof(GridLength),
                                typeof(GridViewCard),
                                default(GridLength),
                                propertyChanged:OnGridLengthChanged);

public GridLength GridWidth
{
    get => (GridLength)GetValue(GridWidthProperty);
    set { SetValue(GridWidthProperty, value); }
}

private static void OnGridLengthChanged(BindableObject bindable, object oldValue, object newValue)
{
    if (bindable is GridViewCard gridView && newValue is GridLength value)
    {
        var column0 = gridView.LeGrid.ColumnDefinitions?.ElementAtOrDefault(0);
        if (column0 != null)
        {
            column0.Width = value;
        }
    }
}

Этот кодоткроет свойство GridLength в UserControl, а также обновит определение столбца сетки (ширина) при изменении свойства.

Этот код устанавливает только ширину первого столбца (как вы указали, будет только один). Но если вы хотите добавить больше столбцов и использовать то же значение, вам просто нужно перебрать коллекцию ColumnDefinition.

3: всякий раз, когда вы используете элемент управления GridViewCard, вы сможете получить доступ к свойству, которое мытолько что создал GridWidth и установите значение.

<DataTemplate>
    <templates:GridViewCard GridWidth="130" />
</DataTemplate>

Но вы указали, что хотите связать значение из ViewModel.

Поскольку вы используете этот пользовательский элемент управления внутри шаблона, а значение исходит из ViewModel (как свойство, а не часть коллекции, привязанной к «списку», вам потребуется выполнить небольшую хитрость.

Давайте добавим свойство к BaseViewModel.

private double _gridColumnLength;
public double GridColumnLength
{
    get => _gridColumnLength;
    set
    {
       //Don't know how you are handling the **Set** and/or Raising of property changes.
      // Modify accordingly (if required)
        _gridColumnLength = value;
        RaisePropertyChanged(nameof(GridColumnLength));
    }
}

Теперь, используя FlowList в качестве примера:

Вы будете использовать имя (x:Name) изFlowList для доступа к BindingContext, а затем к значению свойства.

<flv:FlowListView x:Name="ExploreGridView" 
                IsVisible="{Binding IsGridLayout}" 
                BackgroundColor="Transparent" 
                Margin="{OnIdiom Phone='0,0,20,0',Tablet='0,0,30,0'}" 
                FlowColumnCount="{OnIdiom Phone='2',Tablet='3'}" 
                SeparatorVisibility="None"                 
                HasUnevenRows="true" 
                FlowItemsSource="{Binding HandpickedList}" 
                VerticalScrollBarVisibility="Never">
    <flv:FlowListView.FlowColumnTemplate>
        <DataTemplate>
            <templates:GridViewCard GridWidth="{Binding BindingContext.GridColumnLength, Source={x:Reference ExploreGridView}}" />
        </DataTemplate>
    </flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>

Теперь при установке значения для свойства GridColumnLength моделей ViewModels, которые имеют к нему доступ, произойдет изменение вплоть до таблицы. Column.Width на пользовательском элементе управления GridViewCard.

Надеюсь, это поможет .-

...