Xaml Xamarin自定义视图按钮绑定
我有一个自定义视图,其中有两个按钮-一个在左边,一个在右边 我希望有一个可绑定属性来指示每个按钮将调用哪个函数,但我希望调用的函数位于原始内容页中,而不是自定义控件中 我知道不能将void作为可绑定属性,所以我不确定如何实现这一点 这是我的自定义控件xaml: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"
<?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;
单击的事件处理程序,并在其中调用这些事件
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中定义命令。每当您单击按钮时,都会执行这些命令。您是否能够提供该方法在视图模型中应如何显示的示例?添加了一个示例。