Xaml Xamarin自定义视图按钮绑定

Xaml Xamarin自定义视图按钮绑定,xaml,xamarin,xamarin.forms,custom-controls,buttonclick,Xaml,Xamarin,Xamarin.forms,Custom Controls,Buttonclick,我有一个自定义视图,其中有两个按钮-一个在左边,一个在右边 我希望有一个可绑定属性来指示每个按钮将调用哪个函数,但我希望调用的函数位于原始内容页中,而不是自定义控件中 我知道不能将void作为可绑定属性,所以我不确定如何实现这一点 这是我的自定义控件xaml: <?xml version="1.0" encoding="UTF-8"?> <RelativeLayout xmlns="http://xamarin.com/schemas/2014/forms"

我有一个自定义视图,其中有两个按钮-一个在左边,一个在右边

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

我知道不能将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>
最后,我把定制的新功能也包括进来

<local:HeaderBar></local:HeaderBar>

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

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

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

    <Button Grid.Row="0" Grid.Column="1" Font="Large" Command="{Binding Calculator.KeyPressCommand}" CommandParameter="Eight" Text="8" />
也许有一个更好的解决方案,您可以定义自定义控件的BindingContext,但我的解决方案运行良好

solution-1 您可以在自定义控件中公开几个事件

步骤:

  • 在自定义
    标题栏
    控件中创建2个事件

    public event EventHandler RightButtonClickEvent;
    public event EventHandler LeftButtonClickEvent;
    
  • 在XAML中分配
    单击的
    事件处理程序,并在其中调用这些事件

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

    <local:HeaderBar
       RightButtonClickEvent="OnRightButtonClick"
       LeftButtonClickEvent="OnLeftButtonClick" />
    
    更新的示例代码-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>
    
    <?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>
    
    <?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>
    
    解决方案2(如果使用MVVM,建议使用) 将两个命令作为可绑定属性公开(这些属性将被绑定到内部按钮控件)。然后,您可以将这些新命令绑定到
    ContentPage
    ViewModel

    示例代码-Header.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);
        }
    }
    
    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
        }
    }
    
    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); }
        }
    } 
    
    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.
                    }));
            }   
        }
    }
    
    示例代码-MyContentPage.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>
    
    <?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>
    
    <?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>
    

    谢谢你如此详尽的回答。解决方案2显然最适合我-我的MyContentPage后端代码中需要包含哪些代码才能执行这些命令?MyContentPage后端代码中不需要添加任何代码。您只需要在其ViewModel中定义命令。每当您单击按钮时,都会执行这些命令。您是否能够提供该方法在视图模型中应如何显示的示例?添加了一个示例。