在控制模板中绑定

时间:2016-09-15 00:20:25

标签: xaml xamarin xamarin.forms

使用ControlTemplates相对较新,所以这可能是一个非常简单的问题。但是我在几页上使用了页脚,所以我认为ControlTemplate是个好主意。 我遇到的第一个问题是如何使图像路径绑定。

这是我的App.xaml文件

<Application
xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:abstractions="clr-namespace:SVG.Forms.Plugin.Abstractions;assembly=SVG.Forms.Plugin.Abstractions"
x:Class="MyApp.App">
<Application.Resources>
    <ResourceDictionary>
        <Style x:Key="HomeButtonStyle" TargetType="Button">
            <Setter Property="FontSize" Value="Medium" />
            <Setter Property="TextColor" Value="White" />
            <Setter Property="FontAttributes" Value="Bold"/>
            <Setter Property="BorderWidth" Value="1"/>
            <Setter Property="BorderColor" Value="White"/>
            <Setter Property="BorderRadius" Value="5"/>
            <Setter Property="Margin" Value="16,16,16,0"/>
        </Style>
        <ControlTemplate x:Key="Menu">
            <StackLayout
              Orientation="Horizontal"
              VerticalOptions="End"
              BackgroundColor="Black"
              HeightRequest="70"
              HorizontalOptions="FillAndExpand"
              Spacing="20">
                <abstractions:SvgImage
                    x:Name="Settings"
                    SvgAssembly="{Binding SvgAssembly}"
                    SvgPath="{Binding SettingsIcon}"
                    HeightRequest="50"
                    WidthRequest="50"
                    BackgroundColor="Transparent"
                    VerticalOptions="Center"
                    HorizontalOptions="CenterAndExpand"/>
                <abstractions:SvgImage
                    x:Name="Notification"
                    SvgAssembly="{Binding SvgAssembly}"
                    SvgPath="{Binding Notification}"
                    HeightRequest="50"
                    WidthRequest="50"
                    BackgroundColor="Transparent"
                    VerticalOptions="Center"
                    HorizontalOptions="CenterAndExpand"/>
                <abstractions:SvgImage
                    x:Name="Help"
                    SvgAssembly="{Binding SvgAssembly}"
                    SvgPath="{Binding HelpIcon}"
                    HeightRequest="50"
                    WidthRequest="50"
                    BackgroundColor="Transparent"
                    VerticalOptions="Center"
                    HorizontalOptions="CenterAndExpand"/>
            </StackLayout>
        </ControlTemplate>
    </ResourceDictionary>
</Application.Resources>

然后我如何尝试使用它(HomePage.xaml)......

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:abstractions="clr-namespace:SVG.Forms.Plugin.Abstractions;assembly=SVG.Forms.Plugin.Abstractions"
             x:Class="Page.HomePage">
  <StackLayout>
  ...
<ContentView ControlTemplate="{StaticResource Menu}"></ContentView>

</StackLayout>


</ContentPage>

这是我的HomePage.xaml.cs文件...

public partial class HomePage : ContentPage
{
    public HomePage()
    {
        InitializeComponent();
        BindingContext = new SvgImagesViewModels();

    }
}

ViewModel

public class SvgImagesViewModels
{

    private readonly string _os = DeviceInfo.Hardware.OS == OperatingSystemType.iOS ? "iOS.Images" : "Droid.Images";
    /* The Assembly */ 
    public Assembly SvgAssembly => typeof(App).GetTypeInfo().Assembly;

    /* The Image Paths */ 
    public string UserAvatar => $"{_os}.avatar.svg";
    public string Notification => $"{_os}.bell.svg";
    public string RedNotification => $"{_os}.red_bell.svg"; 
    public string Delete => $"{_os}.delete.svg";
    public string HelpIcon => $"{_os}.help.svg";
    public string Home => $"{_os}.home.svg"; 
    public string SettingsIcon => $"{_os}.settings.svg";
    public string NoImage => $"{_os}.no_image.svg";
    public string Star => $"{_os}.star.svg";
    public string DownCarrot => $"{_os}.down_carrot.svg";
    public string UpCattor => $"{_os}.up_carrot.svg";
    public string RightCarrot => $"{_os}.right_carrot.svg";
    public string LeftCarrot => $"{_os}.left_carrot.svg";
}

这是我得到的错误......

09-14 20:07:22.428 E/mono-rt (11715): [ERROR] FATAL UNHANDLED EXCEPTION: System.AggregateException: One or more errors occurred. ---> System.NullReferenceException: Object reference not set to an instance of an object.
09-14 20:07:22.428 E/mono-rt (11715):   at SVG.Forms.Plugin.Droid.SvgImageRenderer+<<OnElementChanged>b__3_0>d.MoveNext () [0x00020] in <filename unknown>:0 
09-14 20:07:22.428 E/mono-rt (11715):   --- End of inner exception stack trace ---
09-14 20:07:22.428 E/mono-rt (11715):   at (wrapper dynamic-method) System.Object:b7e27031-315a-4ca4-9b10-5b1ac793598c (intptr,intptr)
09-14 20:07:22.428 E/mono-rt (11715):   at (wrapper native-to-managed) System.Object:b7e27031-315a-4ca4-9b10-5b1ac793598c (intptr,intptr)
09-14 20:07:22.428 E/mono-rt (11715): ---> (Inner Exception #0) System.NullReferenceException: Object reference not set to an instance of an object.
09-14 20:07:22.428 E/mono-rt (11715):   at SVG.Forms.Plugin.Droid.SvgImageRenderer+<<OnElementChanged>b__3_0>d.MoveNext () [0x00020] in <filename unknown>:0 <---

所以显然我试图错误地应用BindingContext。

1 个答案:

答案 0 :(得分:1)

在您的ControlTemplate中,您应该使用{TemplateBinding},如下所示:

<ResourceDictionary>
  ...
  <ControlTemplate x:Key="Menu">
    <StackLayout>
      <abstractions:SvgImage
          SvgAssembly="{TemplateBinding SvgAssembly}"
          SvgPath="{TemplateBinding SettingsIcon}" />
          ...
     </StackLayout>
   </ControlTemplate>
</ResourceDictionary>

但是现在你已经TemplateBinding了,你需要定义自己的模板控件

public class Menu : ContentView
{
    public static BindableProperty SvgAssemblyProperty =
        BindableProperty.Create("SvgAssembly", typeof(Assembly), typeof(Menu), null);

    public static BindableProperty SettingsIconProperty =
        BindableProperty.Create("SettingsIcon", typeof(string), typeof(Menu), null);

    ...
}

然后你可以使用它,然后绑定它:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:abstractions="clr-namespace:SVG.Forms.Plugin.Abstractions;assembly=SVG.Forms.Plugin.Abstractions"
             x:Class="Page.HomePage">
  <StackLayout>
    ...
    <Menu ControlTemplate="{StaticResource Menu} SvgAssembly="{Binding SvgAssmbly}" SettingsIcon="{Binding SettingsIcon}" .../>
  </StackLayout>
</ContentPage>

这应该回答你的问题。现在,如果你想要做的就是为每个平台设置不同的图标,那么使用ControlTemplate是过度的。您可以使用OnPlatform,或使用`{x:Static},或者可能使用4-5种不同的方式。玩得开心试验......