Xamarin.forms 如何从Xamarin表单中的DataTemplate条目TextChanged事件调用命令?
正在CollectionView中使用数据模板。。。 我可以通过如下按钮调用ViewModel的命令:Xamarin.forms 如何从Xamarin表单中的DataTemplate条目TextChanged事件调用命令?,xamarin.forms,mvvm,datatemplate,relativesource,eventtocommand,Xamarin.forms,Mvvm,Datatemplate,Relativesource,Eventtocommand,正在CollectionView中使用数据模板。。。 我可以通过如下按钮调用ViewModel的命令: <Button Text="Test" Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}, Path=BindingContext.TestCommand}"/> <Frame.Ge
<Button Text="Test"
Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}},
Path=BindingContext.TestCommand}"/>
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}, Path=BindingContext.TestCommand}"/>
</Frame.GestureRecognizers>
或者通过这样的手势:
<Button Text="Test"
Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}},
Path=BindingContext.TestCommand}"/>
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}, Path=BindingContext.TestCommand}"/>
</Frame.GestureRecognizers>
那么,为什么我不能像这样从条目的TextChanged事件调用该命令呢
<Entry x:Name="PortionEntry"
Text ="{Binding QtyTest, Mode=TwoWay}">
<Entry.Behaviors>
<behavors:EventToCommandBehavior
EventName="TextChanged"
Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}},
Path=BindingContext.TestCommand}"/>
</Entry.Behaviors>
EventToCommandBehavior的代码在数据模板中未使用时有效
以下是一个说明该问题的项目:
我从这些优秀的人那里得到了按钮代码:
谢谢 我测试您的代码,如果我不使用相对源代码绑定,它可以正常工作
<ContentPage
x:Class="demo3.simplecontrol2.Page2"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:customcontrol="clr-namespace:demo3.customcontrol"
xmlns:local="clr-namespace:demo3.simplecontrol2"
x:Name="root">
<ContentPage.Resources>
<DataTemplate x:Key="datatemplate1">
<StackLayout>
<Entry Text="{Binding str, Mode=TwoWay}">
<Entry.Behaviors>
<local:EventToCommandBehavior Command="{Binding Source={x:Reference root}, Path=BindingContext.command1}" EventName="TextChanged" />
</Entry.Behaviors>
</Entry>
</StackLayout>
</DataTemplate>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<Entry Text="123">
<Entry.Behaviors>
<local:EventToCommandBehavior Command="{Binding command1}" EventName="TextChanged" />
</Entry.Behaviors>
</Entry>
<CollectionView ItemTemplate="{StaticResource datatemplate1}" ItemsSource="{Binding entries}">
</CollectionView>
</StackLayout>
</ContentPage.Content>
公共部分类第2页:内容页
{
公共ObservableCollection条目{get;set;}
公共命令command1{get;set;}
公共页2()
{
初始化组件();
条目=新的ObservableCollection()
{
新建testentry(){str=“test 1”},
新建testentry(){str=“test 2”},
新建testentry(){str=“test 3”},
新建testentry(){str=“test 4”},
新建testentry(){str=“test 5”},
新建testentry(){str=“test 6”}
};
command1=新命令(testcommand);
this.BindingContext=this;
}
私有void testcommand()
{
WriteLine(“这是测试!”);
}
}
我测试您的代码,如果我不使用相对源代码绑定,它可以正常工作
<ContentPage
x:Class="demo3.simplecontrol2.Page2"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:customcontrol="clr-namespace:demo3.customcontrol"
xmlns:local="clr-namespace:demo3.simplecontrol2"
x:Name="root">
<ContentPage.Resources>
<DataTemplate x:Key="datatemplate1">
<StackLayout>
<Entry Text="{Binding str, Mode=TwoWay}">
<Entry.Behaviors>
<local:EventToCommandBehavior Command="{Binding Source={x:Reference root}, Path=BindingContext.command1}" EventName="TextChanged" />
</Entry.Behaviors>
</Entry>
</StackLayout>
</DataTemplate>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<Entry Text="123">
<Entry.Behaviors>
<local:EventToCommandBehavior Command="{Binding command1}" EventName="TextChanged" />
</Entry.Behaviors>
</Entry>
<CollectionView ItemTemplate="{StaticResource datatemplate1}" ItemsSource="{Binding entries}">
</CollectionView>
</StackLayout>
</ContentPage.Content>
公共部分类第2页:内容页
{
公共ObservableCollection条目{get;set;}
公共命令command1{get;set;}
公共页2()
{
初始化组件();
条目=新的ObservableCollection()
{
新建testentry(){str=“test 1”},
新建testentry(){str=“test 2”},
新建testentry(){str=“test 3”},
新建testentry(){str=“test 4”},
新建testentry(){str=“test 5”},
新建testentry(){str=“test 6”}
};
command1=新命令(testcommand);
this.BindingContext=this;
}
私有void testcommand()
{
WriteLine(“这是测试!”);
}
}
我查看了您的示例代码,您似乎正在使用来实现您的事件到命令行为
。这也是以大致相同的方式在中实现的注意这些实现继承自Xamarin.Forms.Behavior
我还尝试在分配给ItemsView
的DataTemplate
中执行这些示例的相对源绑定,但是当我运行示例(与上面的示例相同)时,我会在以下位置收到invalidoOperationException
:
Xamarin.Forms.Binding.ApplyRelativeSourceBinding
(Xamarin.Forms.BindableObject targetObject,
Xamarin.Forms.BindableProperty targetProperty)[0x0006c]位于
C:\Advanced Dev\Xamarin.Forms\Xamarin.Forms.Core\Binding.cs:158
转到,您可以看到抛出是由于在binding.ApplyRelativeSourceBinding()
中应用绑定时,绑定targetObject
未继承自Xamarin.Forms.Element
。由于EventToCommandBehavior
继承自Xamarin.Forms.Behavior
这就是结果
他们没有特别提到绑定目标需求,他们显然关心绑定源。但它们确实提到这些绑定搜索可视树或与元素相关:
FindAncestor
指示绑定元素的可视树中的祖先
Self
表示正在设置绑定的元素
由于行为
不是元素
,也不是可视化树的一部分(它存储在VisualElement.Behaviors
属性中),因此绑定在运行时无法直接访问这两个元素以执行其“搜索”,因此绑定永远无法满足要求
我通过扩展条目并在需要的地方添加命令来解决这个问题。它不是最可重用的解决方案,因为我必须在其他元素(如Switch)上使用它,但它可以工作
public class Entry : Xamarin.Forms.Entry
{
public Entry()
{
this.TextChanged += this.OnTextChanged;
}
public static readonly BindableProperty TextChangedCommandProperty =
BindableProperty.Create( nameof( Entry.TextChangedCommand ), typeof( ICommand ), typeof( Entry ) );
public static readonly BindableProperty TextChangedCommandParameterProperty =
BindableProperty.Create( nameof( Entry.TextChangedCommandParameter ), typeof( object ), typeof( Entry ) );
public ICommand TextChangedCommand
{
get => (ICommand)this.GetValue( Entry.TextChangedCommandProperty );
set => this.SetValue( Entry.TextChangedCommandProperty, (object)value );
}
public object TextChangedCommandParameter
{
get => this.GetValue( Entry.TextChangedCommandParameterProperty );
set => this.SetValue( Entry.TextChangedCommandParameterProperty, value );
}
private void OnTextChanged( object sender, TextChangedEventArgs e )
{
if ( this.TextChangedCommand == null ||
!this.TextChangedCommand.CanExecute( this.TextChangedCommandParameter ) )
return;
this.TextChangedCommand.Execute( this.TextChangedCommandParameter );
}
}
以及嵌入在数据模板中的xaml:
<my:Entry Grid.Column="1"
Text="{Binding Value}"
HorizontalTextAlignment="Start"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
VerticalTextAlignment="Center"
Keyboard='Text'
ClearButtonVisibility="WhileEditing"
TextChangedCommand="{Binding BindingContext.TextChangedCommand, Mode=OneTime, Source={RelativeSource FindAncestor, AncestorType={x:Type ItemsView}}}"
TextChangedCommandParameter="{Binding Mode=OneTime}" >
</my:Entry>
<my:EventToCommandObserver Grid.Column="1"
Command="{Binding BindingContext.TextChangedCommand, Mode=OneTime, Source={RelativeSource FindAncestor, AncestorType={x:Type ItemsView}}}"
CommandParameter="{Binding Mode=OneTime}">
<Entry Text="{Binding Value}"
HorizontalTextAlignment="Start"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
VerticalTextAlignment="Center"
Keyboard='Text'
ClearButtonVisibility="WhileEditing"
my:EventToCommandObserver .EventName="TextChanged" />
</my:EventToCommandObserver >
这个替代的xaml嵌入在一个数据模板中
:
<my:Entry Grid.Column="1"
Text="{Binding Value}"
HorizontalTextAlignment="Start"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
VerticalTextAlignment="Center"
Keyboard='Text'
ClearButtonVisibility="WhileEditing"
TextChangedCommand="{Binding BindingContext.TextChangedCommand, Mode=OneTime, Source={RelativeSource FindAncestor, AncestorType={x:Type ItemsView}}}"
TextChangedCommandParameter="{Binding Mode=OneTime}" >
</my:Entry>
<my:EventToCommandObserver Grid.Column="1"
Command="{Binding BindingContext.TextChangedCommand, Mode=OneTime, Source={RelativeSource FindAncestor, AncestorType={x:Type ItemsView}}}"
CommandParameter="{Binding Mode=OneTime}">
<Entry Text="{Binding Value}"
HorizontalTextAlignment="Start"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
VerticalTextAlignment="Center"
Keyboard='Text'
ClearButtonVisibility="WhileEditing"
my:EventToCommandObserver .EventName="TextChanged" />
</my:EventToCommandObserver >
我查看了您的示例代码,您似乎正在使用来实现您的事件到命令行为
。这也是以大致相同的方式在中实现的注意这些实现继承自Xamarin.Forms.Behavior
我还尝试在分配给ItemsView
的DataTemplate
中执行这些示例的相对源绑定,但是当我运行示例(与上面的示例相同)时,我会在以下位置收到invalidoOperationException
:
Xamarin.Forms.Binding.ApplyRelativeSourceBinding
(Xamarin.Forms.BindableObject targetObject,
Xamarin.Forms.BindableProperty targetProperty)[0x0006c]位于
C:\Advanced Dev\Xamarin.Forms\Xamarin.Forms.Core\Binding.cs:158
转到,您可以看到抛出是由于在binding.ApplyRelativeSourceBinding()
中应用绑定时,绑定targetObject
未继承自Xamarin.Forms.Element
。自EventToCommandBehavior
inher