Here is the method that I have come up with so far. However it seems like not such a clean solution.
Does anyone have any suggestions how I could come up with a better solution for doing this?
<?xml version="1.0" encoding="utf-8"?> <StackLayout xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Japanese;assembly=Japanese" x:Class="Japanese.Templates.HeaderTemplate" x:Name="this" HorizontalOptions="FillAndExpand" Orientation="Vertical" Spacing="0" Margin="0"> <StackLayout IsVisible="{Binding HeaderType, Converter={StaticResource HeaderType1BoolConverter}, Source={x:Reference this} }" > <!-- code --> </StackLayout> <StackLayout IsVisible="{Binding HeaderType, Converter={StaticResource HeaderType2BoolConverter}, Source={x:Reference this} }" > <!-- code --> </StackLayout> </StackLayout>
In my bank end CS:
using System; using System.Collections.Generic; using Xamarin.Forms; namespace Japanese.Templates { public partial class HeaderTemplate : StackLayout { public HeaderTemplate() { InitializeComponent(); } public static readonly BindableProperty HeaderTypeProperty = BindableProperty.Create( nameof(HeaderType), typeof(string), typeof(DataViewCellTemplate), default(string)); public string HeaderType { get { return (string)GetValue(HeaderTypeProperty); } set { SetValue(HeaderTypeProperty, value); } } } }
Converter Code:
public class HeaderType1BoolConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return object.Equals(value, "1"); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } public class HeaderType2BoolConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return object.Equals(value, "2"); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
In the calling code:
<template:HeaderTemplate Header="Application" HeaderType="1" />
2 Answers
Answers 1
Using triggers is an option.
For e.g.: You can add property-triggers to check the value on HeaderType
and accordingly update the Content
(or layout) in your custom control HeaderView
.
Please note in this case we are extending from ContentView
not StackLayout
on the assumption that only one layout/control is visible at a time.
XAML
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:SampleApp" x:Class="SampleApp.HeaderView"> <ContentView.Triggers> <!-- if header type is 1, use header1 layout --> <Trigger TargetType="local:HeaderView" Property="HeaderType" Value="1"> <Setter Property="Content"> <Setter.Value> <Label Text="Header1" /> </Setter.Value> </Setter> </Trigger> <!-- if header type is 2, use header2 layout --> <Trigger TargetType="local:HeaderView" Property="HeaderType" Value="2"> <Setter Property="Content"> <Setter.Value> <StackLayout> <Label Text="Header2" /> <BoxView HeightRequest="1" BackgroundColor="Gray" /> </StackLayout> </Setter.Value> </Setter> </Trigger> <!-- you can add more layouts here if you need --> </ContentView.Triggers> <!-- add default content that can be displayed in case of no match --> <StackLayout> <Label Text="DefaultHeader" /> <BoxView HeightRequest="1" BackgroundColor="Gray" /> </StackLayout> </ContentView>
Code-behind
public partial class HeaderView : ContentView { public HeaderView() { InitializeComponent(); } public static readonly BindableProperty HeaderTypeProperty = BindableProperty.Create( nameof(HeaderType), typeof(string), typeof(HeaderView), defaultValue: default(string)); public string HeaderType { get { return (string)GetValue(HeaderTypeProperty); } set { SetValue(HeaderTypeProperty, value); } } }
Usage
<local:HeaderView HeaderType="1" />
Answers 2
I believe that what you are looking is a ControlTemplate here is an implementation.
App.xaml
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleTheme.App"> <Application.Resources> <ResourceDictionary> <ControlTemplate x:Key="Header1Template"> <StackLayout> <!-- code --> </StackLayout> </ControlTemplate> <ControlTemplate x:Key="Header2Template"> <StackLayout> <!-- code --> </StackLayout> </ControlTemplate> </ResourceDictionary> </Application.Resources> </Application>
Usage (This will make header1 your default, you can pick any of the both)
<ContentView x:Name="contentView" ControlTemplate="{StaticResource Header1Template}">
Now there are many ways to change the header, either by defining as the default code above or with an action which can be a button click like the example given on the link or with a propertyChange event, if you want to depend on a property to choose the header like:
public int HeaderNumber { get; set; } protected override void OnPropertyChanged([CallerMemberName] string propertyName = null) { base.OnPropertyChanged(propertyName); if (propertyName == "HeaderNumber") { contentView.ControlTemplate = (HeaderNumber == 1) ? Header1Template : Header2Template; } }
Note that i never implemented a ControlTemplate but i think this solves your problem.
0 comments:
Post a Comment