【问题标题】:How to do alternative binding with ControlTemplate in Xamarin Forms如何在 Xamarin Forms 中使用 ControlTemplate 进行替代绑定
【发布时间】:2020-07-01 23:40:40
【问题描述】:

我正在使用 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>

为了动态显示返回按钮,我在OnAppearingBasePage.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 是 > 1,我也想强制关闭后退按钮

现在,我通过在 BasePage 中使用同名 IsBackButtonVisibleBindableProperty 来实现基于上面的脏编码

我的问题是,有没有办法为 ControlTemplate 做替代绑定,我知道有 FallBackValue 和 Default 用于普通绑定(当然它们只是不绑定的值)但我不想硬编码它似乎是 TemplateBinding不支持那些(智能不会显示这些选项)

我想要做的是将BasePage 中的BindableProperty 重命名为ForceNoBackButton,并使导航栏不可见,尽管有 ViewModel 绑定。

有什么方法可以根据条件在TemplateBinding 中进行替代绑定..

  1. 如果 BindingContext 是 BaseViewModel 的类型,则使用 Property IsBackButtonVisible

  2. 如果页面BindingContext是这个页面或者不是BaseViewModel,则回退到BasePage本地BindablePropertyForceNoBackButton

  3. 我可以使用 BindableProperty 的 propertychanged 事件处理程序吗?如果是,如何。如果可视元素在当前 XAML 中,我知道该怎么做,不知道如何为 TemplatedView

【问题讨论】:

    标签: c# xaml xamarin.forms binding templatebinding


    【解决方案1】:

    您可以在BasePage 上创建两个可绑定属性IsBackButtonVisibleForceNoBackButton

    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;
        }
    

    要使关联的视图模型与此属性保持同步 - 您可以在 BasePage.xaml 上设置绑定,BasePage() 构造函数中添加以下行以编程方式设置此绑定。

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

    还建议为ForceNoBackButton 使用属性更改处理程序 - 这样您就可以处理对其值的更改(如果它们发生在页面已经加载之后)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-29
      • 2015-11-17
      • 2020-12-30
      • 1970-01-01
      • 1970-01-01
      • 2013-02-23
      • 1970-01-01
      • 2017-06-16
      相关资源
      最近更新 更多