Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 导航返回后,Xamarin.Forms中未显示菜单项_C#_Xamarin_Xamarin.android_Xamarin.forms_Searchview - Fatal编程技术网

C# 导航返回后,Xamarin.Forms中未显示菜单项

C# 导航返回后,Xamarin.Forms中未显示菜单项,c#,xamarin,xamarin.android,xamarin.forms,searchview,C#,Xamarin,Xamarin.android,Xamarin.forms,Searchview,我正在开发一个Xamarin.Forms Android应用程序,其中在ContentPage上使用CustomRenderer在页面标题中显示SearchView。“SearchPage”类的CustomRenderer如下所示: /// <summary> /// The search page renderer. /// </summary> public class SearchPageRenderer : PageRenderer { ///

我正在开发一个Xamarin.Forms Android应用程序,其中在ContentPage上使用CustomRenderer在页面标题中显示SearchView。“SearchPage”类的CustomRenderer如下所示:

 /// <summary>
///     The search page renderer.
/// </summary>
public class SearchPageRenderer : PageRenderer
{
    /// <summary>
    ///     Gets or sets the search view.
    /// </summary>
    private SearchView searchView;

    /// <summary>
    ///     Gets or sets the toolbar.
    /// </summary>
    private Toolbar toolbar;

    /// <summary>
    ///     Reaction on the disposing of the page.
    /// </summary>
    /// <param name="disposing">A value indicating whether disposing.</param>
    protected override void Dispose(bool disposing)
    {
        if (this.searchView != null)
        {
            this.searchView.QueryTextChange -= this.OnQueryTextChangeSearchView;
        }

        this.toolbar?.Menu?.RemoveItem(Resource.Menu.mainmenu);
        base.Dispose(disposing);
    }

    /// <summary>
    ///     Reaction on the element changed event.
    /// </summary>
    /// <param name="e">The event argument.</param>
    protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
    {
        base.OnElementChanged(e);

        if (e?.NewElement == null || e.OldElement != null)
        {
            return;
        }

        this.AddSearchToToolBar();
    }

    /// <summary>
    ///     Adds a search item to the toolbar.
    /// </summary>
    private void AddSearchToToolBar()
    {
        this.toolbar = (CrossCurrentActivity.Current?.Activity as MainActivity)?.FindViewById<Toolbar>(Resource.Id.toolbar);

        if (this.toolbar != null)
        {
            this.toolbar.Title = this.Element.Title;
            this.toolbar.InflateMenu(Resource.Menu.mainmenu);

            this.searchView = this.toolbar.Menu?.FindItem(Resource.Id.action_search)?.ActionView?.JavaCast<SearchView>();

            if (this.searchView != null)
            {
                this.searchView.QueryTextChange += this.OnQueryTextChangeSearchView;
                this.searchView.ImeOptions = (int)ImeAction.Search;
                this.searchView.MaxWidth = int.MaxValue;
                this.searchView.SetBackgroundResource(Resource.Drawable.textfield_search_holo_light);
            }
        }
    }

    /// <summary>
    ///     Reaction on the text change event of the searchbar.
    /// </summary>
    /// <param name="sender">The event sender.</param>
    /// <param name="e">The event argument.</param>
    private void OnQueryTextChangeSearchView(object sender, SearchView.QueryTextChangeEventArgs e)
    {
        var searchPage = this.Element as SearchPage;
        searchPage?.SearchCommand?.Execute(e?.NewText);
    }
}
这是没有问题的。但是,如果用户使用后退按钮从“DetailPage”导航回“SearchPage”,则定制的搜索标题根本不会显示

我尝试的是:

使用页面的“OnAppearing”事件而不是“OnElementChanged”。乍一看,这并不能解决问题。但是,如果我将Task.Delay(500)添加到OnAppearing方法,然后再次添加SearchView,它就会显示出来。但是这个补丁看起来很难看,如果我在使用SearchPage时休眠应用程序并继续,搜索小部件会显示两次

所以我的问题是:

Xamarin中是否有bug,或者我做错了什么?

Xamarin有缺陷还是我做错了什么

我不能说这是一只虫子,我宁愿把它当作设计来考虑。真正的问题是,您试图在自定义渲染器中修改
工具栏
,并且根据您的描述,您正在使用
导航页面
,每次更改当前页面时,它都会更新
工具栏
的视图

因此,您使用页面的“OnAppearing”事件而不是“OnElementChanged”是正确的,这会导致另一个问题,
工具栏
的更新会在删除旧页面时延迟,正如您在
RemovePage
方法的源代码中看到的那样,当显示新页面时,
OnAppearing
方法将立即执行:

Device.StartTimer(TimeSpan.FromMilliseconds(10), () =>
{
    UpdateToolbar();
    return false;
});
所以我不认为你也做错了什么,你使用的方法是等待任务。延迟(500)可以快速解决此问题

根据您在此处的描述:

但是这个补丁看起来很难看,如果我在使用SearchPage时休眠应用程序并继续,搜索小部件会显示两次

我建议将您的
搜索页面
更改为
视图
,然后从页面中动态添加/删除此视图:

public class SearchPage : View
{
  ...
}
和它的渲染器(其他代码相同,仅更改为继承自
ViewRenderer
,并且
OnElementChanged
的参数不同):

主页
的布局:

<StackLayout>
   ...
</StackLayout>
顺便说一下,如果您想从这里的
MainPage
导航到其他页面,您可以这样编码:

this.Navigation.PushAsync(new Page1());

无需为其创建
PushPageAsync
任务

尝试在重新启动时覆盖
。我最近发现了一个实例,当视图回到前面时,需要重新绑定我的列表,这个方法被称为Consistently,您最终选择了什么解决方案?忘了说,我建议使用
ViewRenderer
而不是
PageRenderer
的原因是,我不知道您如何再次添加
SearchPage
,您也可以直接尝试在
OnDisappearing
中删除它。非常感谢您的回答!看来任务延迟是必要的。我喜欢您使用视图而不是页面进行自定义渲染的想法,因此我将尝试一下:添加等待任务的意义是什么。延迟(500);在OnAppearing方法中?@user3713398,正如我在回答中所说的,在
NavigationPageRenderer
的源代码中,在
RemovePage
方法中,它在那里被硬编码以延迟一点。@GraceFeng:你的逻辑工作得很有魅力。非常感谢。您是否也可以发送IOS的ViewRenderer。
MainPage = new NavigationPage(new MainPage());
<StackLayout>
   ...
</StackLayout>
protected override async void OnAppearing()
{
    base.OnAppearing();
    await Task.Delay(500);
    var content = this.Content as StackLayout;
    content.Children.Add(new SearchPage());
}

protected override void OnDisappearing()
{
    base.OnDisappearing();
    var content = this.Content as StackLayout;
    foreach (var child in content.Children)
    {
        var searchpage = child as SearchPage;
        if (searchpage != null)
        {
            content.Children.Remove(searchpage);
            return;
        }
    }
}
this.Navigation.PushAsync(new Page1());