Как сделать альтернативное связывание с ControlTemplate в Xamarin Forms - PullRequest
0 голосов
/ 20 марта 2020

Я использую ControlTemplate, имеют согласованную панель навигации по Android и iOS

<ControlTemplate x:Key="NavBarTemplate">
    <StackLayout>
        <StackLayout Orientation="Horizontal" 
            VerticalOptions="CenterAndExpand" 
            IsVisible="{TemplateBinding BindingContext.IsBackButtonVisible, Mode=TwoWay}">
            <Label Text="&lt;" 
                FontSize="Large" 
                FontAttributes="Bold" 
                HorizontalTextAlignment="Center" 
                VerticalOptions="FillAndExpand" 
                VerticalTextAlignment="Center" 
                Margin="20,0,0,0" />
            <Label TextColor="{StaticResource DarkGrey}" 
                HorizontalOptions="StartAndExpand" 
                HorizontalTextAlignment="Center" 
                VerticalOptions="FillAndExpand" 
                VerticalTextAlignment="Center" 
                FontSize="Small" 
                Text="Back" />
            <StackLayout.GestureRecognizers>
                <TapGestureRecognizer Command="{TemplateBinding BindingContext.NavigateBackCommand}" />
            </StackLayout.GestureRecognizers>
        </StackLayout>
        <Image Source="logo.png" 
            VerticalOptions="Center" />
    </StackLayout>
</ControlTemplate>

. Для динамического отображения кнопки «назад» я добавил код ниже OnAppearing из BasePage.cs

protected override void OnAppearing () 
{
    base.OnAppearing ();

    if (BindingContext is BaseViewModel viewmodel) 
    {
        if(Application.Current.MainPage as NavigationPage nav)
        {

            if(nav.Navigation.NavigationStack.Count >1 )
            {
                viewmodel.IsBackButtonVisible = true;
            }else
            {
                viewmodel.IsBackButtonVisible = false;
            }
            //dirty coding force to false
            if (!this.IsBackButtonVisible) //refers to local BindableProperty
            {
                viewmodel.IsBackButtonVisible = false;
            }
        }else //no viewmodel found just use localbinding 
        {
            BindingContext = this;
        }
    }
}

Так что на некоторых страницах я хочу принудительно отключить кнопку Назад, даже если NavigationStack is> 1

Сейчас я достигаю основанного на Dirty-кодировке выше, имея BindableProperty в BasePage с тем же именем IsBackButtonVisible

Мой вопрос: есть ли способ сделать альтернативное связывание для ControlTemplate, я знаю, что есть FallBackValue и Default для обычного связывания (которые являются просто значениями, не связывающими конечно) но я не хочу жестко кодировать его, и кажется, что TemplateBinding не поддерживает их (intellisence не будет показывать эти параметры)

Я хочу переименовать BindableProperty в BasePage в ForceNoBackButton и сделать навигацию панель невидима, несмотря на привязку ViewModel.

Есть ли способ сделать альтернативную привязку в TemplateBinding на основе условий ..

  1. Если BindingContext является типом BaseViewMo del затем используйте Property IsBackButtonVisible

  2. Иначе, если страница BindingContext является этой страницей или чем-то отличным от BaseViewModel, тогда отступите к BasePage local BindableProperty т.е. ForceNoBackButton

  3. Могу ли я сделать это с помощью обработчика события с измененным свойством BindableProperty? Если да, то как. Я знаю, как это сделать, если визуальный элемент находится в текущем XAML, не знаю, как это сделать для TemplatedView

1 Ответ

1 голос
/ 21 марта 2020

Вы можете создать два привязываемых свойства IsBackButtonVisible и ForceNoBackButton для BasePage.

public static readonly BindableProperty ForceNoBackButtonProperty =
    BindableProperty.Create(
    "ForceNoBackButton", typeof(bool), typeof(BasePage),
    defaultValue: default(bool));

public static readonly BindableProperty IsBackButtonVisibleProperty =
    BindableProperty.Create(
    "IsBackButtonVisible", typeof(bool), typeof(BasePage),
    defaultValue: default(bool));

И обновите свой управляющий шаблон, чтобы просто использовать IsBackButtonVisible

<ControlTemplate x:Key="NavBarTemplate">
    ...
    <StackLayout Orientation="Horizontal" 
        ..
        IsVisible="{TemplateBinding IsBackButtonVisible}">

при изменении метода OnAppearing() следующим образом:

protected override void OnAppearing()
{
    ..
    if (nav.Navigation.NavigationStack.Count > 1)
    {
        IsBackButtonVisible = !ForceNoBackButton;
    }
    else
    {
        IsBackButtonVisible = false;
    }

Сохранить соответствующая модель представления в syn c с этим свойством - вы можете установить привязку на BasePage.xaml, или добавить следующую строку в конструкторе BasePage(), чтобы установить эту привязку программно.

public BasePage()
{
    InitializeComponent();
    SetBinding(IsBackButtonVisibleProperty,
         new Binding(nameof(BaseViewModel.IsBackButtonVisible), 
              mode: BindingMode.OneWayToSource));
}

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

...