如何在 Xamarin Forms 中使用 ControlTemplate 进行替代绑定
How to do alternative binding with ControlTemplate in Xamarin Forms
我正在使用 ControlTemplate
在 Android 和 iOS
之间有一致的导航栏
<ControlTemplate x:Key="NavBarTemplate">
<StackLayout>
<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand"
IsVisible="{TemplateBinding BindingContext.IsBackButtonVisible, Mode=TwoWay}">
<Label Text="<"
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>
为了动态显示后退按钮,我在 BasePage.cs
的 OnAppearing
中添加了以下代码
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 中使用相同的名称 BindableProperty
IsBackButtonVisible
我的问题是,有没有办法为 ControlTemplate
做替代绑定,我知道普通绑定有 FallBackValue 和 Default(当然它们只是不绑定的值)但我不想硬编码它似乎 TemplateBinding 不支持那些(智能不会显示这些选项)
我想做的是将 BasePage
中的 BindableProperty
重命名为 ForceNoBackButton
并使导航栏不可见,尽管有 ViewModel 绑定。
有什么方法可以根据条件在 TemplateBinding
中进行替代绑定..
如果 BindingContext 是 BaseViewModel 的类型,则使用 属性 IsBackButtonVisible
否则,如果页面 BindingContext
是此页面或 BaseViewModel
以外的其他页面,则回退到 BasePage
本地 BindableProperty
即 ForceNoBackButton
我可以使用 Bindable属性 的 propertychanged 事件处理程序来实现吗?如果是,如何。如果视觉元素在当前 XAML 中,我知道如何做,不知道如何为 TemplatedView
做
您可以在 BasePage
上创建两个可绑定属性 IsBackButtonVisible
和 ForceNoBackButton
。
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
、 或 上设置绑定,在 [=20] 中添加以下行=] 构造函数以编程方式设置此绑定。
public BasePage()
{
InitializeComponent();
SetBinding(IsBackButtonVisibleProperty,
new Binding(nameof(BaseViewModel.IsBackButtonVisible),
mode: BindingMode.OneWayToSource));
}
还建议为 ForceNoBackButton
设置一个 属性-changed 处理程序 - 这样您就可以处理对其值的更改(如果它们发生在页面加载之后)。
我正在使用 ControlTemplate
在 Android 和 iOS
<ControlTemplate x:Key="NavBarTemplate">
<StackLayout>
<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand"
IsVisible="{TemplateBinding BindingContext.IsBackButtonVisible, Mode=TwoWay}">
<Label Text="<"
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>
为了动态显示后退按钮,我在 BasePage.cs
OnAppearing
中添加了以下代码
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 中使用相同的名称 BindableProperty
IsBackButtonVisible
我的问题是,有没有办法为 ControlTemplate
做替代绑定,我知道普通绑定有 FallBackValue 和 Default(当然它们只是不绑定的值)但我不想硬编码它似乎 TemplateBinding 不支持那些(智能不会显示这些选项)
我想做的是将 BasePage
中的 BindableProperty
重命名为 ForceNoBackButton
并使导航栏不可见,尽管有 ViewModel 绑定。
有什么方法可以根据条件在 TemplateBinding
中进行替代绑定..
如果 BindingContext 是 BaseViewModel 的类型,则使用 属性
IsBackButtonVisible
否则,如果页面
BindingContext
是此页面或BaseViewModel
以外的其他页面,则回退到BasePage
本地BindableProperty
即ForceNoBackButton
我可以使用 Bindable属性 的 propertychanged 事件处理程序来实现吗?如果是,如何。如果视觉元素在当前 XAML 中,我知道如何做,不知道如何为
TemplatedView
做
您可以在 BasePage
上创建两个可绑定属性 IsBackButtonVisible
和 ForceNoBackButton
。
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
、 或 上设置绑定,在 [=20] 中添加以下行=] 构造函数以编程方式设置此绑定。
public BasePage()
{
InitializeComponent();
SetBinding(IsBackButtonVisibleProperty,
new Binding(nameof(BaseViewModel.IsBackButtonVisible),
mode: BindingMode.OneWayToSource));
}
还建议为 ForceNoBackButton
设置一个 属性-changed 处理程序 - 这样您就可以处理对其值的更改(如果它们发生在页面加载之后)。