英文:
How to use UserStoppedTypingBehavior from ControlTemplate?
问题
在我的.NET MAUI应用程序中,我创建了一个自定义搜索控件和其控件模板。当我运行应用程序并执行搜索时,SearchCommand没有被触发。
如果我直接将Entry控件添加到TestPage并添加行为,那么它就能正常工作。
<Entry Grid.Row="0"
HorizontalOptions="FillAndExpand"
Placeholder="在此输入...">
<Entry.Behaviors>
<toolkit:UserStoppedTypingBehavior
Command="{Binding Path=SearchCommand}"
StoppedTypingTimeThreshold="1000"
MinimumLengthThreshold="3"
ShouldDismissKeyboardAutomatically="True" />
</Entry.Behaviors>
</Entry>
自定义控件
/// <summary>
/// 表示一个Entry控件,样式包含搜索图标,当输入文本更改时触发新的搜索命令。
/// </summary>
public class SearchField : MobileContentViewBase
{
// 自定义控件的逻辑
private Entry _searchFieldEntry;
private const string SearchFieldEntryName = nameof(_searchFieldEntry);
protected override void AddCustomHandlers()
{
if (_searchFieldEntry == null)
{
_searchFieldEntry = this.FindChildByClassId<Entry>(SearchFieldEntryName);
}
}
}
App.xaml
<ControlTemplate x:Key="SearchFieldTemplate">
<StackLayout>
<ctrls:IconButton
ImageSource="Search"
BackgroundColor="Transparent" />
<Entry
ClassId="_searchFieldEntry"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Entry.Behaviors>
<toolkit:UserStoppedTypingBehavior
Command="{Binding Path=BindingContext.SearchCommand}"
StoppedTypingTimeThreshold="1000"
MinimumLengthThreshold="3"
ShouldDismissKeyboardAutomatically="True" />
</Entry.Behaviors>
</Entry>
</StackLayout>
</ControlTemplate>
<Style TargetType="ctrls:SearchField">
<Setter Property="ControlTemplate" Value="{StaticResource Key=SearchFieldTemplate}" />
</Style>
TestPage.xaml
<myCtrl:SearchField
x:Name="searchField"
Grid.Row="0"
HorizontalOptions="FillAndExpand"
Placeholder="在此搜索..." />
TestPageViewModel.cs
public ICommand SearchCommand { get; set; }
public TestPageViewModel()
{
SearchCommand = new Command<string>(PerformSearch);
}
private void PerformSearch(string searchTerms)
{
PerformedSearches += $"搜索了 '{searchTerms}'{Environment.NewLine}";
}
除了简单的绑定外,我还尝试了使用位于SearchFieldTemplate中的Entry控件的TemplateBinding,但它会引发InvalidOperationException异常。
有没有人知道如何使其工作?任何帮助都将不胜感激。
英文:
In my .NET MAUI app, I have created a custom search control and ControlTemplate for it. When I'm running the app and perform search the SearchCommand is not getting fired.
If I add the Entry control directly to TestPage and add behavior then its working.
<Entry Grid.Row="0"
HorizontalOptions="FillAndExpand"
Placeholder="type here...">
<Entry.Behaviors>
<toolkit:UserStoppedTypingBehavior
Command="{Binding Path=SearchCommand}"
StoppedTypingTimeThreshold="1000"
MinimumLengthThreshold="3"
ShouldDismissKeyboardAutomatically="True" />
</Entry.Behaviors>
</Entry>
Custom control
/// <summary>
/// Represents an Entry control styled to contain a search icon
/// and trigger a new search command when the entry text changes.
/// </summary>
public class SearchField : MobileContentViewBase
{
//Logic of custom control
private Entry _searchFieldEntry;
private const string SearchFieldEntryName = nameof(_searchFieldEntry);
protected override void AddCustomHandlers()
{
if (_searchFieldEntry == null)
{
_searchFieldEntry = this.FindChildByClassId<Entry>(SearchFieldEntryName);
}
}
}
App.xaml
<ControlTemplate x:Key="SearchFieldTemplate">
<StackLayout>
<ctrls:IconButton
ImageSource="Search"
BackgroundColor="Transparent" />
<Entry
ClassId="_searchFieldEntry"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Entry.Behaviors>
<toolkit:UserStoppedTypingBehavior
Command="{Binding Path=BindingContext.SearchCommand}"
StoppedTypingTimeThreshold="1000"
MinimumLengthThreshold="3"
ShouldDismissKeyboardAutomatically="True" />
</Entry.Behaviors>
</Entry>
</StackLayout>
</ControlTemplate>
<Style TargetType="ctrls:SearchField">
<Setter Property="ControlTemplate" Value="{StaticResource Key=SearchFieldTemplate}" />
</Style>
TestPage.xaml
<myCtrl:SearchField
x:Name="searchField"
Grid.Row="0"
HorizontalOptions="FillAndExpand"
Placeholder="Search here..." />
TestPageViewModel.cs
public ICommand SearchCommand { get; set; }
public TestPageViewModel()
{
SearchCommand = new Command<string>(PerformSearch);
}
private void PerformSearch(string searchTerms)
{
PerformedSearches += $"Performed search for '{searchTerms}'{Environment.NewLine}";
}
Instead of simple Binding I have tried TemplateBinding as well with Entry control which is in SearchFieldTemplate but it throws an InvalidOperationException.
Does anyone know how to make it work? Any help will be highly appreciated.
答案1
得分: 1
行为没有唯一的可视树父级,因此我们无法在其上使用RelativeSource绑定。您还可以参考此问题:Relativesource绑定和行为。
解决方法:
尽管我们无法为行为使用RelativeSource绑定,但我们可以使用TemplateBinding来为Entry或StackLayout设置Binding,然后引用它。请考虑下面的代码:
在App.xaml中:
<Entry x:Name="myentry" BindingContext="{Binding BindingContext, Source={RelativeSource TemplatedParent}}"
ClassId="_searchFieldEntry"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Entry.Behaviors>
<toolkit:UserStoppedTypingBehavior
Command="{Binding Path=BindingContext.SearchCommand,Source={x:Reference myentry}}"
StoppedTypingTimeThreshold="1000"
MinimumLengthThreshold="3"
ShouldDismissKeyboardAutomatically="True" />
</Entry.Behaviors>
</Entry>
在上面的代码中,我们首先使用TemplateBinding来设置Entry的BindingContext(x:Name="myentry")。然后为行为设置Binding源为Entry。
希望这对您有所帮助。
英文:
Behaviours don't have unique visual tree parents so we cannot use RelativeSource binding on it. You could also refer to this issue: Relativesource bindings and behaviors.
Workaround:
Although we cannot use RelativeSource binding for behavior, we could use TemplateBinding for Entry or StackLayout, then refer to it. Consider the code below:
In App.xaml:
<Entry x:Name="myentry" BindingContext="{Binding BindingContext, Source={RelativeSource TemplatedParent}}"
ClassId="_searchFieldEntry"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Entry.Behaviors>
<toolkit:UserStoppedTypingBehavior
Command="{Binding Path=BindingContext.SearchCommand,Source={x:Reference myentry}}"
StoppedTypingTimeThreshold="1000"
MinimumLengthThreshold="3"
ShouldDismissKeyboardAutomatically="True" />
</Entry.Behaviors>
</Entry>
In the above code, we first use TemplateBinding to set the BindingContext for Entry (x:Name="myentry"). Then for Behavior set the Binding Source to the Entry.
Hope it works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。



评论