如何在ControlTemplate中使用UserStoppedTypingBehavior?

huangapple go评论62阅读模式
英文:

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.

&lt;Entry Grid.Row=&quot;0&quot;
       HorizontalOptions=&quot;FillAndExpand&quot;
       Placeholder=&quot;type here...&quot;&gt;
        &lt;Entry.Behaviors&gt;
            &lt;toolkit:UserStoppedTypingBehavior
                Command=&quot;{Binding Path=SearchCommand}&quot;
                StoppedTypingTimeThreshold=&quot;1000&quot;
                MinimumLengthThreshold=&quot;3&quot;
                ShouldDismissKeyboardAutomatically=&quot;True&quot; /&gt;
        &lt;/Entry.Behaviors&gt;
&lt;/Entry&gt;

Custom control

/// &lt;summary&gt;
/// Represents an Entry control styled to contain a search icon
/// and trigger a new search command when the entry text changes.
/// &lt;/summary&gt;
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&lt;Entry&gt;(SearchFieldEntryName);
        }
    }
}

App.xaml

&lt;ControlTemplate x:Key=&quot;SearchFieldTemplate&quot;&gt;
    &lt;StackLayout&gt;
        &lt;ctrls:IconButton
            ImageSource=&quot;Search&quot;
            BackgroundColor=&quot;Transparent&quot; /&gt;

        &lt;Entry
            ClassId=&quot;_searchFieldEntry&quot;
            HorizontalOptions=&quot;FillAndExpand&quot;
            VerticalOptions=&quot;FillAndExpand&quot;&gt;
            &lt;Entry.Behaviors&gt;
                &lt;toolkit:UserStoppedTypingBehavior
                    Command=&quot;{Binding Path=BindingContext.SearchCommand}&quot;
                    StoppedTypingTimeThreshold=&quot;1000&quot;
                    MinimumLengthThreshold=&quot;3&quot;
                    ShouldDismissKeyboardAutomatically=&quot;True&quot; /&gt;
            &lt;/Entry.Behaviors&gt;
        &lt;/Entry&gt;
    &lt;/StackLayout&gt;
&lt;/ControlTemplate&gt;
&lt;Style TargetType=&quot;ctrls:SearchField&quot;&gt;
    &lt;Setter Property=&quot;ControlTemplate&quot; Value=&quot;{StaticResource Key=SearchFieldTemplate}&quot; /&gt;
&lt;/Style&gt;

TestPage.xaml

&lt;myCtrl:SearchField
    x:Name=&quot;searchField&quot;
    Grid.Row=&quot;0&quot;
    HorizontalOptions=&quot;FillAndExpand&quot;
    Placeholder=&quot;Search here...&quot; /&gt;

TestPageViewModel.cs

public ICommand SearchCommand { get; set; }

public TestPageViewModel()
{
    SearchCommand = new Command&lt;string&gt;(PerformSearch);
}

private void PerformSearch(string searchTerms)
{
    PerformedSearches += $&quot;Performed search for &#39;{searchTerms}&#39;{Environment.NewLine}&quot;;
}

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。

希望这对您有所帮助。

如何在ControlTemplate中使用UserStoppedTypingBehavior?

英文:

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:

&lt;Entry x:Name=&quot;myentry&quot; BindingContext=&quot;{Binding BindingContext, Source={RelativeSource TemplatedParent}}&quot;
    ClassId=&quot;_searchFieldEntry&quot;
    HorizontalOptions=&quot;FillAndExpand&quot;
    VerticalOptions=&quot;FillAndExpand&quot;&gt;
    &lt;Entry.Behaviors&gt;
        &lt;toolkit:UserStoppedTypingBehavior
            Command=&quot;{Binding Path=BindingContext.SearchCommand,Source={x:Reference myentry}}&quot;
            StoppedTypingTimeThreshold=&quot;1000&quot;
            MinimumLengthThreshold=&quot;3&quot;
            ShouldDismissKeyboardAutomatically=&quot;True&quot; /&gt;
    &lt;/Entry.Behaviors&gt;
&lt;/Entry&gt;

In the above code, we first use TemplateBinding to set the BindingContext for Entry (x:Name=&quot;myentry&quot;). Then for Behavior set the Binding Source to the Entry.

Hope it works.

如何在ControlTemplate中使用UserStoppedTypingBehavior?

huangapple
  • 本文由 发表于 2023年6月1日 22:40:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76383082.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定