具有两个选择器事件句柄的Xamarin控制模板

时间:2019-02-27 14:47:26

标签: c# xamarin xamarin.forms

我有一个带有两个选择器的xamarin控制模板,并添加到app.xml中,我在两个页面的“首页和详细信息”中使用该模板,我想:

  1. 如何在使用此模板的所有页面上保持选择器选择的索引。
  2. 如何处理所有页面上两个选择器的selectedindexchange事件,例如:(当索引更改时将标签文本设置为所选文本)

PS:我的选择器项源将在运行时根据我的模型进行设置。并根据第一选择器的选择项,第二选择器的源将发生变化。

app.xaml

<?xml version="1.0" encoding="UTF-8"?>
<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="ActiveProfileTemplate">
                <Grid Padding="5,0,0,0" BackgroundColor="#f7f6fb">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="0.1*" />
                        <RowDefinition Height="0.8*" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <BoxView Grid.ColumnSpan="2"/>
                    <Picker x:Name="FirstPicker" Title="FirstPicker" SelectedIndex="{TemplateBinding Parent.FirstPickerSelectedIndex}" Grid.Column="0" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="180" FontSize="Small" TextColor="#214189">
                        <Picker.Items>
                            <x:String>FirstPicker_1</x:String>
                            <x:String>FirstPicker_2</x:String>
                            <x:String>FirstPicker_3</x:String>
                            <x:String>FirstPicker_4</x:String>
                            <x:String>FirstPicker_5</x:String>
                        </Picker.Items>
                    </Picker>
                    <Picker x:Name="SecondPicker" Title="SecondPicker" SelectedIndex="{TemplateBinding Parent.SecondPickerSelectedIndex}" Grid.Column="1" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="210" FontSize="Small" TextColor="#214189" >
                        <Picker.Items>
                            <x:String>SecondPicker_1</x:String>
                            <x:String>SecondPicker_2</x:String>
                            <x:String>SecondPicker_3</x:String>
                            <x:String>SecondPicker_4</x:String>
                            <x:String>SecondPicker_5</x:String>
                        </Picker.Items>
                    </Picker>
                    <ContentPresenter Grid.Row="1" Grid.ColumnSpan="2"/>
                </Grid>
            </ControlTemplate>
        </ResourceDictionary>
    </Application.Resources>
</Application>

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" x:Class="SimpleTheme.HomePage">
    <ContentView x:Name="contentView" Padding="0,20,0,0" ControlTemplate="{StaticResource ActiveProfileTemplate}">
        <StackLayout VerticalOptions="CenterAndExpand">
            <Label Text="Welcome to the HomePage!" HorizontalOptions="Center" />
            <Label x:Name="lbl_firstpicker" Text="First Picker Selected Item" HorizontalOptions="Center" TextColor="DarkRed"/>
            <Label x:Name="lbl_secondpicker" Text="Second Picker Selected Item" HorizontalOptions="Center" TextColor="DarkRed"/>
        </StackLayout>
    </ContentView>
</ContentPage>

HomePage.cs

public partial class HomePage : ContentPage
{
    public static readonly BindableProperty FirstPickerSelectedIndexProperty = BindableProperty.Create(
        "FirstPickerSelectedIndex",
        typeof(int),
        typeof(HomePage),
        2);
    public static readonly BindableProperty SecondPickerSelectedIndexProperty = BindableProperty.Create(
        "SecondPickerSelectedIndex",
        typeof(int),
        typeof(HomePage),
        3);

    public int FirstPickerSelectedIndex => (int)GetValue(FirstPickerSelectedIndexProperty);
    public int SecondPickerSelectedIndex => (int)GetValue(SecondPickerSelectedIndexProperty);

    public HomePage()
    {
            InitializeComponent();
     }
}

DetailPage.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"
             x:Class="SimpleTheme.DetailPage">
    <ContentView x:Name="contentView" Padding="0,20,0,0" ControlTemplate="{StaticResource ActiveProfileTemplate}">
        <StackLayout VerticalOptions="CenterAndExpand">
            <Label Text="Welcome to the DetailPage!" HorizontalOptions="Center" />
            <Label x:Name="lbl_firstpicker" Text="First Picker Selected Item" HorizontalOptions="Center" TextColor="Teal" />
            <Label x:Name="lbl_secondpicker" Text="Second Picker Selected Item" HorizontalOptions="Center" TextColor="Teal" />
        </StackLayout>
    </ContentView>
</ContentPage>

Screenshot Screenshot

1 个答案:

答案 0 :(得分:1)

由于我找不到设置侦听器的好方法,因此我使用自定义ContentView来包含ControlTemplate的布局,如下所示:

MyView.xaml

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="App5.MyView">
  <ContentView.Content>
    <Grid Padding="5,0,0,0" BackgroundColor="#f7f6fb">
        <Grid.RowDefinitions>
            <RowDefinition Height="0.1*" />
            <RowDefinition Height="0.8*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <BoxView Grid.ColumnSpan="2"/>
        <Picker x:Name="FirstPicker" Title="FirstPicker"    Grid.Column="0" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="180" FontSize="Small" TextColor="#214189" >
        </Picker>
        <Picker x:Name="SecondPicker" Title="SecondPicker"   Grid.Column="1" HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="210" FontSize="Small" TextColor="#214189" >
        </Picker>
        <ContentPresenter Grid.Row="1" Grid.ColumnSpan="2"/>
    </Grid>
  </ContentView.Content>
</ContentView>

MyView.xaml.cs

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MyView : ContentView
 {

    public MyView()
    {
        InitializeComponent();
        List<FirstModel> listFirstModel = new List<FirstModel>();
        listFirstModel.Add(new FirstModel { Key = "Pl", Description = "DescPl" });
        listFirstModel.Add(new FirstModel { Key = "Ps", Description = "DescPs" });
        listFirstModel.Add(new FirstModel { Key = "En", Description = "DescEn" });
        listFirstModel.Add(new FirstModel { Key = "H", Description = "DescH" });

        List<SecondModel> listSecondModel = new List<SecondModel>();
        listSecondModel.Add(new SecondModel { FirstModelKey = "Pl", Key = "Pl1", Description = "SecondModelPl1" });
        listSecondModel.Add(new SecondModel { FirstModelKey = "Pl", Key = "Pl2", Description = "SecondModelPl2" });
        listSecondModel.Add(new SecondModel { FirstModelKey = "Pl", Key = "Pl3", Description = "SecondModelPl3" });

        listSecondModel.Add(new SecondModel { FirstModelKey = "Ps", Key = "Ps1", Description = "SecondModelPs1" });
        listSecondModel.Add(new SecondModel { FirstModelKey = "Ps", Key = "Ps2", Description = "SecondModelPs2" });
        listSecondModel.Add(new SecondModel { FirstModelKey = "Ps", Key = "Ps3", Description = "SecondModelPs3" });

        listSecondModel.Add(new SecondModel { FirstModelKey = "En", Key = "En1", Description = "SecondModelEn1" });
        listSecondModel.Add(new SecondModel { FirstModelKey = "En", Key = "En2", Description = "SecondModelEn2" });
        listSecondModel.Add(new SecondModel { FirstModelKey = "En", Key = "En3", Description = "SecondModelEn3" });

        listSecondModel.Add(new SecondModel { FirstModelKey = "H", Key = "H1", Description = "SecondModelH1" });
        listSecondModel.Add(new SecondModel { FirstModelKey = "H", Key = "H2", Description = "SecondModelH2" });
        listSecondModel.Add(new SecondModel { FirstModelKey = "H", Key = "H3", Description = "SecondModelH3" });


        foreach (FirstModel fm in listFirstModel)
        {
            FirstPicker.Items.Add(fm.Description);
        }
        FirstPicker.SelectedIndexChanged += (sender, e) => {

            SecondPicker.Items.Clear();

            string key = listFirstModel[FirstPicker.SelectedIndex].Key;
            foreach (SecondModel sm in listSecondModel.FindAll(o => o.FirstModelKey == key))
                SecondPicker.Items.Add(sm.Description);

        };

       // use MessagingCenter to get the SelectedIndex and set it
        MessagingCenter.Subscribe<string, int>("firstpicker", "indext", (sender, args) => {
            FirstPicker.SelectedIndex = args;
        });
        MessagingCenter.Subscribe<string, int>("secondpicker", "indext", (sender, args) => {
            SecondPicker.SelectedIndex = args;
        });
    }


}

HomePage.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:App5"
         x:Class="App5.HomePage">

    <StackLayout x:Name="ss" VerticalOptions="CenterAndExpand">
    //use the custom contentView
    <local:MyView x:Name="mv"></local:MyView>
    <Label Text="Welcome to the HomePage!" HorizontalOptions="Center" />
        <Label x:Name="lbl_firstpicker" Text="First Picker Selected Item" HorizontalOptions="Center" TextColor="DarkRed"/>
        <Label x:Name="lbl_secondpicker" Text="Second Picker Selected Item" HorizontalOptions="Center" TextColor="DarkRed"/>
    <Button Text="todetail" Clicked="Button_Clicked"/>
</StackLayout>

HomePage.xaml.cs

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class HomePage : ContentPage
{
    private int firstSelectedIndex;
    private int secondSelectedIndex;

    public HomePage()
    {
        InitializeComponent();
        //find the picker control and set listener
        Picker p = mv.FindByName<Picker>("FirstPicker");
        Picker s = mv.FindByName<Picker>("SecondPicker");
        p.SelectedIndexChanged += FirstPicker_SelectedIndexChanged;
        s.SelectedIndexChanged += SecondPicker_SelectedIndexChanged;
    }
    void FirstPicker_SelectedIndexChanged(object sender, EventArgs e)
    {
        var picker = (Picker)sender;
        firstSelectedIndex = picker.SelectedIndex;
        if (firstSelectedIndex != -1)
        {
            lbl_firstpicker.Text = picker.Items[firstSelectedIndex];
        }

    }
    void SecondPicker_SelectedIndexChanged(object sender, EventArgs e)
    {
        var picker = (Picker)sender;
        secondSelectedIndex = picker.SelectedIndex;

        if (secondSelectedIndex != -1)
        {
            lbl_secondpicker.Text = picker.Items[secondSelectedIndex];
        }
    }
    // navigation to detailpage and notice Picker to set the selected indext
    async void Button_Clicked(object sender, EventArgs e)
    {
        await Navigation.PushAsync(new DetailPage());
        MessagingCenter.Send<string, int>("firstpicker", "indext", firstSelectedIndex);
        MessagingCenter.Send<string, int>("secondpicker", "indext", secondSelectedIndex);
    }
}

模型:通过按键实现链接

class FirstModel
{
    public string Key { get; set; }
    public string Description { get; set; }

    public FirstModel()
    {
    }
}

class SecondModel
{
    public string FirstModelKey { get; set; }
    public string Key { get; set; }
    public string Description { get; set; }

    public SecondModel()
    {
    }
}

DetailsPage 主页

相似