Xamarin 自定义视图按钮绑定

Mar*_*ley 3 xaml custom-controls buttonclick xamarin xamarin.forms

我有一个带有 2 个按钮的自定义视图 - 一个在左侧,一个在右侧。

我想要一个可绑定的属性来指示每个按钮将调用哪个函数,但我想要调用的函数是在原始内容页面中,而不是在自定义控件中。

我知道您不能将 void 作为可绑定属性,所以我不确定如何实现这一点。

这是我的自定义控件 xaml:

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns="http://xamarin.com/schemas/2014/forms" 
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="EngineerApp.HeaderBar"  HeightRequest="50">
    <BoxView x:Name="banner" BackgroundColor="#edeff2"
        RelativeLayout.WidthConstraint="{ ConstraintExpression 
            Type=RelativeToParent,
            Property=Width,
            Factor=1 }"
        RelativeLayout.HeightConstraint="{ ConstraintExpression 
        Type=RelativeToParent,
        Property=Height,
        Factor=1 }">
    </BoxView>
    <Button 
        Text="Left"
        x:Name="btnLeft"
        Style="{StaticResource headerBarButton}"
        RelativeLayout.WidthConstraint="{ ConstraintExpression 
            Type=RelativeToView,
            ElementName=banner,
            Property=Width,
            Factor=0.5 }"       
        RelativeLayout.HeightConstraint="{ ConstraintExpression 
            Type=RelativeToView,
            ElementName=banner,
            Property=Height,
            Factor=1 }"
        >
    </Button>
    <Button 
        Text="Right" 
        Style="{StaticResource headerBarButton}"
        RelativeLayout.XConstraint="{ ConstraintExpression 
            Type=RelativeToView,
            ElementName=banner,
            Property=Width, 
            Factor=0.5,
            Constant=1
        }"
        RelativeLayout.WidthConstraint="{ ConstraintExpression 
            Type=RelativeToView,
            ElementName=banner,
            Property=Width,
            Factor=0.5 }"       
        RelativeLayout.HeightConstraint="{ ConstraintExpression 
            Type=RelativeToView,
            ElementName=banner,
            Property=Height,
            Factor=1 }"
        >
    </Button>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

这是后端代码:

using System;
using System.Collections.Generic;
using System.Windows.Input;
using Xamarin.Forms;

namespace EngineerApp
{
    public partial class HeaderBar : RelativeLayout
    {

        public HeaderBar()
        {

            InitializeComponent();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

最后我像往常一样包括自定义新

<local:HeaderBar></local:HeaderBar>
Run Code Online (Sandbox Code Playgroud)

如何将 2 个按钮单击事件中的每一个绑定到我的内容页面中的方法?

Sha*_*raj 5

解决方案1

您可以在自定义控件中公开几个事件。

脚步:

  1. 在您的自定义控件中创建 2 个事件HeaderBar

    public event EventHandler RightButtonClickEvent;
    public event EventHandler LeftButtonClickEvent;
    
    Run Code Online (Sandbox Code Playgroud)
  2. Clicked在 XAML 中分配事件处理程序,并在其中调用这些事件

    void RightButton_Clicked(object sender, EventArgs e)
    {
        RightButtonClickEvent?.Invoke(sender, e);
    }
    
    void LeftButton_Clicked(object sender, EventArgs e)
    {
        LeftButtonClickEvent?.Invoke(sender, e);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将自定义事件与您的事件处理程序绑定 ContentPage

    <local:HeaderBar
       RightButtonClickEvent="OnRightButtonClick"
       LeftButtonClickEvent="OnLeftButtonClick" />
    
    Run Code Online (Sandbox Code Playgroud)

示例代码 - HeaderBar.xaml.cs

public partial class HeaderBar : RelativeLayout
{
    public HeaderBar()
    {
        InitializeComponent();
    }

    public event EventHandler RightButtonClickEvent;
    public event EventHandler LeftButtonClickEvent;

    void RightButton_Clicked(object sender, EventArgs e)
    {
        RightButtonClickEvent?.Invoke(sender, e);
    }

    void LeftButton_Clicked(object sender, EventArgs e)
    {
        LeftButtonClickEvent?.Invoke(sender, e);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新的示例代码 - HeaderBar.xaml

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="EngineerApp.HeaderBar"  HeightRequest="50">
<BoxView x:Name="banner" BackgroundColor="#edeff2"
    RelativeLayout.WidthConstraint="{ ConstraintExpression 
        Type=RelativeToParent,
        Property=Width,
        Factor=1 }"
    RelativeLayout.HeightConstraint="{ ConstraintExpression 
    Type=RelativeToParent,
    Property=Height,
    Factor=1 }">
</BoxView>
<Button 
    Text="Left"
    x:Name="btnLeft"
    Clicked="LeftButton_Clicked"
    Style="{StaticResource headerBarButton}"
    RelativeLayout.WidthConstraint="{ ConstraintExpression 
        Type=RelativeToView,
        ElementName=banner,
        Property=Width,
        Factor=0.5 }"       
    RelativeLayout.HeightConstraint="{ ConstraintExpression 
        Type=RelativeToView,
        ElementName=banner,
        Property=Height,
        Factor=1 }"
    >
</Button>
<Button 
    Text="Right" 
    x:Name="btnRight"
    Clicked="RightButton_Clicked"
    Style="{StaticResource headerBarButton}"
    RelativeLayout.XConstraint="{ ConstraintExpression 
        Type=RelativeToView,
        ElementName=banner,
        Property=Width, 
        Factor=0.5,
        Constant=1
    }"
    RelativeLayout.WidthConstraint="{ ConstraintExpression 
        Type=RelativeToView,
        ElementName=banner,
        Property=Width,
        Factor=0.5 }"       
    RelativeLayout.HeightConstraint="{ ConstraintExpression 
        Type=RelativeToView,
        ElementName=banner,
        Property=Height,
        Factor=1 }"
    >
</Button>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

示例代码 - MyContentPage.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:local="clr-namespace:EngineerApp" 
  x:Class="EngineerApp.MyContentPage">
  <local:HeaderBar
    RightButtonClickEvent="OnRightButtonClick"
    LeftButtonClickEvent="OnLeftButtonClick" />
</ContentPage>
Run Code Online (Sandbox Code Playgroud)

示例代码 - MyContentPage.xaml.cs

public partial class MyContentPage : ContentPage
{
    public MyContentPage()
    {
        InitializeComponent();
    }

    void OnRightButtonClick(object sender, EventArgs e)
    {
        //handle right-button click here
    }

    void OnLeftButtonClick(object sender, EventArgs e)
    {
        //handle left-button click here
    }
}
Run Code Online (Sandbox Code Playgroud)

解决方案 2(如果您使用的是 MVVM,则推荐使用)

将两个命令公开为可绑定属性(这些属性又将绑定到内部按钮控件)。然后,您可以将这些新命令绑定到您的ContentPage's 中的属性ViewModel

示例代码 - Header.xaml.cs

public partial class HeaderBar : RelativeLayout
{
    public HeaderBar()
    {
        InitializeComponent();

        //create binding between parent control and child controls
        btnLeft.SetBinding(Button.CommandProperty, new Binding(nameof(LeftButtonCommand), source: this));
        btnRight.SetBinding(Button.CommandProperty, new Binding(nameof(RightButtonCommand), source: this));
    }

    public static readonly BindableProperty LeftButtonCommandProperty =
        BindableProperty.Create(
        "ILeftButtonCommand", typeof(ICommand), typeof(HeaderBar),
            defaultValue: null);

    public ICommand LeftButtonCommand
    {
        get { return (ICommand)GetValue(LeftButtonCommandProperty); }
        set { SetValue(LeftButtonCommandProperty, value); }
    }

    public static readonly BindableProperty RightButtonCommandProperty =
        BindableProperty.Create(
        "RightButtonCommand", typeof(ICommand), typeof(HeaderBar),
            defaultValue: null);

    public ICommand RightButtonCommand
    {
        get { return (ICommand)GetValue(RightButtonCommandProperty); }
        set { SetValue(RightButtonCommandProperty, value); }
    }
} 
Run Code Online (Sandbox Code Playgroud)

示例代码 - MyContentPage.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:local="clr-namespace:EngineerApp" 
  x:Class="EngineerApp.MyContentPage">
  <local:HeaderBar
      LeftButtonCommand="{Binding LeftClickCommand}"
      RightButtonCommand="{Binding RightClickCommand}" />
</ContentPage>
Run Code Online (Sandbox Code Playgroud)

示例代码 - MyContentPageViewModel.cs

public class MyContentPageViewModel : ViewModelBase //base implementation for INotifyPropertyChanged
{
    private ICommand _leftClickCommand; 
    public ICommand LeftClickCommand
    {
        get
        {
            return _leftClickCommand ??
                (_leftClickCommand = new Command((obj) =>
                {
                    //handle left button click here.
                }));
        }
    }

    private ICommand _rightClickCommand;
    public ICommand RightClickCommand
    {
        get
        {
            return _rightClickCommand ??
                (_rightClickCommand = new Command((obj) =>
                {
                    //handle right button click here.
                }));
        }   
    }
}
Run Code Online (Sandbox Code Playgroud)