【问题标题】:Events and Delegates in Xamarin forms parent and child pagesXamarin 中的事件和委托表单父页面和子页面
【发布时间】:2020-12-07 00:28:09
【问题描述】:

我需要一些帮助。我是事件和处理程序的新手,我想开始使用事件来解耦,但我很困惑。

我有一个类,我有一个在 OnAppearing 上填充的列表视图。但是,为了防止每次单击页面时都发生 onAppearing,我加载了一次列表,然后我希望在通过使用事件从服务器添加或删除时将项目添加或删除到列表中。

ListView 页面是我最喜欢的报纸文章链接列表。当点击这些链接中的任何一个时,我会被重定向到 LinksDetailsPage,我在其中传递所选链接,然后显示与该链接相关的任何详细信息。

无论如何...

我想在我的收藏夹列表中无缝添加或删除一个项目。因此,当我单击 LinksDetailsPage 中的 AddItem 或 RemoveItem 时,我希望将该项目删除或添加到收藏夹页面列表中。在我只依靠 OnAppearing 发挥它的魔力并更新收藏夹列表之前,但是从列表中删除该项目会滞后,所以我希望它会在调用 even 时立即删除或添加,而不是在页面在 OnAppearing 上加载。但是我认为我要么没有正确调用事件,要么我的订阅者没有正确订阅。事件和代表从一开始就让我感到困惑。最重要的是,我的收藏夹列表被分组,这也是我第一次使用分组列表。 查看我的代码:

订阅者 我的收藏页面:

 public FavoritesPage()
        {
            InitializeComponent();
           
        }
        protected override async void OnAppearing()
        {

            if (_isDataLoaded)
                return;

            _isDataLoaded = true;
            base.OnAppearing();
            await LoadFavorites();

        }

        private async Task LoadFavorites()
        {
            groups = new ObservableCollection<LinksTypeGroup<string, NewspaperLink>>();
           
            var links = await _db.GetAllFavorites();
            
                var linkType = await _manager.GetLinkCategories();
                foreach(var type in linkType)
                {
                   
                    var typegroup = links.FindAll(
                    delegate(NewspaperLink link)
                    {   
                        return link.iLinkTypeID == type.iLinkTypeID;
                    });
              
                    groups.Add(new LinksTypeGroup<string, NewspaperLink>(type.Title, typegroup));
              
                
                MyList.GroupDisplayBinding = new Binding("GroupKey");
                MyList.ItemsSource = groups;
               

            }
        }
 public void Listener(FavoritesPage P)
        {
            P.LinkAdded += Item_Added;
            P.LinkDeleted += Item_Deleted;
            
        }
void Item_Deleted(object sender, int e)
        {
            Console.WriteLine("Item_Deleted");
// remove item from groups ..see code above

        }

 void Item_Added(object sender, int e)
        {
            Console.WriteLine("Item_Added");
// add to groups ..see code above

        }

到目前为止,我没有访问任何内容。

出版商 链接详情页:

    private NewspaperLink _link;
    public event EventHandler< NewspaperLink> ItemAdded;
    public event EventHandler< NewspaperLink> ItemDeleted;

  public LinksDetailsPage(NewspaperLink link)
        {
           
            _link = link; 
            BindingContext = _link;
            InitializeComponent();
        }

        protected override async void OnAppearing()
        {
            base.OnAppearing();
            

            await LoadLink();
        }

        private async Task LoadLink()
        {
            var url = await db.ReturnRecipeLink(_link.iLinkID);
            
                    linkWebView.Source = url;
                
                  CheckifExists(_link);
            }
        }

  void AddLink(object sender, System.EventArgs e)
        {
            var link = BindingContext as NewspaperLink;
            db.InsertIntoMyList(_link);
            ItemAdded?.Invoke(this, link);
  
            
        }

   void  DeleteLink(object sender, System.EventArgs e)
        {

            var link = BindingContext as NewspaperLink;
             db.DeleteFromMyList(_link);
             ItemDeleted?.Invoke(this, link);
    
        }

有人可以指导我如何使这个均匀过程起作用吗?

【问题讨论】:

  • 您永远不会调用订阅您的事件的Listener 方法,所以当然没有任何反应。我建议您考虑使用 MessagingCenter 作为处理此问题的替代方法。

标签: c# xamarin event-handling


【解决方案1】:

如果想使用 EventsLinksDetailsPage 应该声明如下:

public partial class LinksDetailsPage : ContentPage
{
    public event EventHandler<NewspaperLink> ItemAdded;
    public event EventHandler<NewspaperLink> ItemDeleted;
    public LinksDetailsPage()
    {
        InitializeComponent();
    }

    protected virtual void AddLink(NewspaperLink e)
    {
        EventHandler<NewspaperLink> handler = ItemAdded;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    protected virtual void DeleteLink( NewspaperLink e)
    {
        EventHandler<NewspaperLink> handler = ItemDeleted;
        if (handler != null)
        {
            handler(this, e);
        }
    }
     
    // Add click event
    private void Add_Clicked(object sender, EventArgs e)
    {
        AddLink(new NewspaperLink() {link="first link" });
    }

    // Delete click event
    private void Delete_Clicked(object sender, EventArgs e)
    {
        DeleteLink(new NewspaperLink() { link = "first link" });
    }
}

public class NewspaperLink : EventArgs
{
    public string link { get; set; }
}

然后导航到LinksDetailsPage页面时需要在ListView页面订阅:

private async void Button_Clicked(object sender, EventArgs e)
{
    LinksDetailsPage detailPage = new LinksDetailsPage();
    detailPage.ItemAdded += DetailGridPage_ItemAdded;
    detailPage.ItemDeleted += DetailGridPage_ItemDeleted;
    await Navigation.PushModalAsync(detailGridPage);
}

private void DetailGridPage_ItemDeleted(object sender, NewspaperLink e)
{
    Console.WriteLine("The tlink was deleted : " + e.link);
}

private void DetailGridPage_ItemAdded(object sender, NewspaperLink e)
{
    Console.WriteLine("The link was added : "+e.link);
}

同样,如果要使用Delegate,只需要在List Page中声明如下:

public partial class ListViewPage : ContentPage
{
    public delegate void ItemAddedDelegate(NewspaperLink e);
    public delegate void ItemDeletedDelegate(NewspaperLink e);

    public ListViewPage()
    {
        InitializeComponent();
    }

    private async void Button_Clicked(object sender, EventArgs e)
    {
        ItemAddedDelegate itemAddedDelegate = AddMethod;
        ItemDeletedDelegate itemDeletedDelegate = DeleteMethod;
        DetailGridPage detailGridPage = new DetailGridPage(itemAddedDelegate, itemDeletedDelegate);
        await Navigation.PushModalAsync(detailGridPage);
    }

    public static void AddMethod(NewspaperLink item)
    {
        Console.WriteLine("Add" + item.link);
    }
    public static void DeleteMethod(NewspaperLink link)
    {
        Console.WriteLine("Delete" + item.link);
    }

}

然后在LinksDetailsPage中,可以将adddelete委托方法传递给ListViewPage

public partial class LinksDetailsPage : ContentPage
{
    private ListViewPage.ItemAddedDelegate itemAddedDelegate;
    private ListViewPage.ItemDeletedDelegate itemDeletedDelegate;
 
    public DetailGridPage()
    {
        InitializeComponent();
    }

    public LinksDetailsPage(ListViewPage.ItemAddedDelegate itemAddedDelegate, ListViewPage.ItemDeletedDelegate itemDeletedDelegate)
    {
        InitializeComponent();
        this.itemAddedDelegate = itemAddedDelegate;
        this.itemDeletedDelegate = itemDeletedDelegate;
    }
   
    // Add click event
    private void Add_Clicked(object sender, EventArgs e)
    {
        itemAddedDelegate(new NewspaperLink() { link = "first link" });
    }

    // Delete click event
    private void Delete_Clicked(object sender, EventArgs e)
    {
        itemDeletedDelegate(new NewspaperLink() { link = "first link" });
    }
}

public class NewspaperLink : EventArgs
{
    public string link { get; set; }
}

如果使用MessageCenter,它应该是实现这一目标的最佳便捷方法。

ListView 页面中只有Subscribe它:

public ListViewPage()
{
    InitializeComponent();

    MessagingCenter.Subscribe<object, NewspaperLink>(this, "Add", async (sender, arg) =>
    {
        await DisplayAlert("Message received", "arg=" + arg.link, "OK");
    });

    MessagingCenter.Subscribe<object, NewspaperLink>(this, "Delete", async (sender, arg) =>
    {
        await DisplayAlert("Message received", "arg=" + arg.link, "OK");
    });
}

并在LinksDetailsPage中发送消息如下:

// Add click event
private void Add_Clicked(object sender, EventArgs e)
{
    NewspaperLink newspaperLink= new NewspaperLink() { link = "first link" };
    MessagingCenter.Send<object, NewspaperLink>(this, "Add", newspaperLink);
}
// Delete click event
private void Delete_Clicked(object sender, EventArgs e)
{
    NewspaperLink newspaperLink = new NewspaperLink() { link = "first link" };
    MessagingCenter.Send<object, NewspaperLink>(this, "Delete", newspaperLink);
}

【讨论】:

  • 谢谢!你解开了我的很多困惑。我将使用事件方法。现在我对它有了更多的了解,我认为这个选项对我来说更好。
猜你喜欢
  • 2016-10-03
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-21
  • 2021-12-17
  • 1970-01-01
相关资源
最近更新 更多