Xamarin自定义视图按钮绑定

时间:2017-05-09 22:48:49

标签: xaml xamarin xamarin.forms custom-controls buttonclick

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

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

我知道你不能作为可绑定属性的空白,所以我不知道如何实现这一点。

这是我的自定义控件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>

这是后端代码:

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

namespace EngineerApp
{
    public partial class HeaderBar : RelativeLayout
    {

        public HeaderBar()
        {

            InitializeComponent();
        }

    }
}

最后,我通过

包含自定义新内容
<local:HeaderBar></local:HeaderBar>

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

2 个答案:

答案 0 :(得分:2)

解-1

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

<强>步骤:

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

    public event EventHandler RightButtonClickEvent;
    public event EventHandler LeftButtonClickEvent;
    
  2. 在XAML中分配Clicked个事件处理程序,并在其中调用这些事件

    void RightButton_Clicked(object sender, EventArgs e)
    {
        RightButtonClickEvent?.Invoke(sender, e);
    }
    
    void LeftButton_Clicked(object sender, EventArgs e)
    {
        LeftButtonClickEvent?.Invoke(sender, e);
    }
    
  3. 使用ContentPage

    中的事件处理程序绑定自定义事件
    <local:HeaderBar
       RightButtonClickEvent="OnRightButtonClick"
       LeftButtonClickEvent="OnLeftButtonClick" />
    
  4. 示例代码 - 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);
        }
    }
    

    更新了示例代码 - 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>
    

    示例代码 - 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>
    

    示例代码 - 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
        }
    }
    

    解决方案-2(建议使用MVVM时)

    将两个命令公开为可绑定属性(后者将绑定到内部按钮控件)。然后,您可以将这些新命令绑定到ContentPage的{​​{1}}

    中的属性

    示例代码 - Header.xaml.cs

    ViewModel

    示例代码 - MyContentPage.xaml

    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); }
        }
    } 
    

    示例代码 - MyContentPageViewModel.cs

    <?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>
    

答案 1 :(得分:0)

我有类似的问题。 我创建了一个CalculatorPage.xaml(我的自定义控件)和一个链接的CalculatorViewModel。

对于我的自定义控件中的每个按钮:

    <Button Grid.Row="0" Grid.Column="1" Font="Large" Command="{Binding Calculator.KeyPressCommand}" CommandParameter="Eight" Text="8" />

在上面的示例中,CalculatorViewModel中存在“KeyPressCommand”。但“计算器”不存在。

我创建了一个新的MainView(我的主视图)和相应的MainViewModel。

正如您所做的那样,我将自定义控件包含在我的XAML中,如下所示:

<common:CalculatorView></common:CalculatorView>

在MainViewModel中,我有一个属性

public CalculatorViewModel Calculator { get; private set; } = new CalculatorViewModel();

可能有一个更好的解决方案,你定义自定义控件的BindingContext但我的解决方案工作正常