我创建了一个名为HeaderTemplate的自定义视图。该控件具有图像。我想要实现的是单击Image并使用MVVM执行一些操作。
请在下面找到该控件的xml和cs。
HeaderTemplate.xml
appl_id
HeaderTemplate.xml.cs
emp_id
我的页面(HolidaysView)具有此自定义控件以及“图像点击/点击”命令。
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="PS.Views.Templates.HeaderTemplate"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:behaviors="clr-namespace:PS.Behaviors">
<ContentView.Content>
<StackLayout
Padding="10"
BackgroundColor="Transparent"
Orientation="Horizontal">
<Image
x:Name="ImageSource_2"
HeightRequest="50"
HorizontalOptions="EndAndExpand"
Source="{Binding ImageSource2}">
<Image.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="1" Tapped="ImageSource2_Tapped" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
</ContentView.Content>
</ContentView>
此页面的绑定视图模型包含命令
public partial class HeaderTemplate : ContentView
{
public HeaderTemplate()
{
InitializeComponent();
BindingContext = this;
}
public static readonly BindableProperty ImageSource2Property =
BindableProperty.Create(nameof(ImageSource2), typeof(string), typeof(HeaderTemplate));
public string ImageSource2
{
get => (string)GetValue(ImageSource2Property);
set => SetValue(ImageSource2Property, value);
}
public static readonly BindableProperty ImageSource2TapCommandProperty =
BindableProperty.Create(nameof(ImageSource2TapCommand),
typeof(ICommand),
typeof(HeaderTemplate),
null);
public ICommand ImageSource2TapCommand
{
get => (ICommand)GetValue(ImageSource2TapCommandProperty);
set => SetValue(ImageSource2TapCommandProperty, value);
}
private void ImageSource2_Tapped(object sender, EventArgs e)
{
if (ImageSource2TapCommand == null) return;
if (ImageSource2TapCommand.CanExecute(null))
{
ImageSource2TapCommand.Execute(null);
}
}
}
不起作用。我不知道我哪里错了。 我想念什么吗? 我对此进行了大量研究,但仍然找不到任何解决方案。
谢谢!
答案 0 :(得分:3)
要使其正常工作,您只需要做几处更改。
首先,在ContenView类文件中,删除BindingContext = this;
行。
然后,您需要向两个BindableProperty中添加PropertyChanged
处理程序
public static readonly BindableProperty ImageSource2Property =
BindableProperty.Create(nameof(ImageSource2),
typeof(string),
typeof(HeaderTemplate),
defaultValue: default(string),
propertyChanged: OnImageSourcePropertyChanged);
public static readonly BindableProperty ImageSource2TapCommandProperty =
BindableProperty.Create(
propertyName: nameof(ImageSource2TapCommand),
returnType: typeof(ICommand),
declaringType: typeof(HeaderTemplate),
defaultValue: default(ICommand),
propertyChanged: OnTapCommandPropertyChanged);
如果您看不到它们之间的区别,那么我在谈论以下内容:OnImageSourcePropertyChanged
和OnTapCommandPropertyChanged
。我只是添加了propertyName,所以Create方法中的其他更改不是必需的,因此更加清楚。
您当然需要实现这两种方法:
static void OnTapCommandPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
if(bindable is HeaderTemplate headerTemplate && newValue is ICommand command)
{
headerTemplate.ImageSource2TapCommand = command;
}
}
static void OnImageSourcePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is HeaderTemplate headerTemplate && newValue is string imageSource)
{
headerTemplate.ImageSource_2.Source = ImageSource.FromFile(imageSource);
}
}
通过这些更改,您应该可以点击Image
并根据需要导航。
原因是什么?
由于您是在首次创建自定义控件时将“主页”上的值绑定到自定义控件,因此这些值是null
,这就是为什么您需要收听值更改的原因,并且可以通过添加创建方法上的onPropertyChanged
实现。
在this帖子中也有很好的解释。
您的完整班级看起来应该类似于:
public partial class HeaderTemplate : ContentView
{
public HeaderTemplate()
{
InitializeComponent();
}
public static readonly BindableProperty ImageSource2Property =
BindableProperty.Create(nameof(ImageSource2),
typeof(string),
typeof(HeaderTemplate),
defaultValue: default(string),
propertyChanged: OnImageSourcePropertyChanged);
public string ImageSource2
{
get => (string)GetValue(ImageSource2Property);
set => SetValue(ImageSource2Property, value);
}
public static readonly BindableProperty ImageSource2TapCommandProperty =
BindableProperty.Create(
propertyName: nameof(ImageSource2TapCommand),
returnType: typeof(ICommand),
declaringType: typeof(HeaderTemplate),
defaultValue: default(ICommand),
propertyChanged: OnTapCommandPropertyChanged);
public ICommand ImageSource2TapCommand
{
get => (ICommand)GetValue(ImageSource2TapCommandProperty);
set => SetValue(ImageSource2TapCommandProperty, value);
}
private void ImageSource2_Tapped(object sender, EventArgs e)
{
if (ImageSource2TapCommand == null) return;
if (ImageSource2TapCommand.CanExecute(null))
{
ImageSource2TapCommand.Execute(null);
}
}
static void OnTapCommandPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
if(bindable is HeaderTemplate headerTemplate && newValue is ICommand command)
{
headerTemplate.ImageSource2TapCommand = command;
}
}
static void OnImageSourcePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is HeaderTemplate headerTemplate && newValue is string imageSource)
{
headerTemplate.ImageSource_2.Source = ImageSource.FromFile(imageSource);
}
}
}
希望这会有所帮助。-
注意:尝试遵循其他答案之一中发布的示例,以使用Command属性更改TapEvent。
答案 1 :(得分:2)
TapGestureRecognizer
class具有Command
property {接受{1}}
我只是在类似于您的自定义控件中尝试过,并且工作正常。
所以,用于结合ICommand
到ICommand
,使用TapGestureRecognizer
属性,而不是Command
的事件。
Tap
答案 2 :(得分:0)
将Source
的{{1}}中的BindingContext
设置为ICommand
。
ContentPage
示例:
MyViewCommand="{{Binding Path=BindingContext.NavigateToCommand, Source={x:Reference MyContentPage}}}"