/// <summary>
 /// Конструктор.
 /// </summary>
 /// <param name="link">Ссылка.</param>
 /// <param name="favorites">Избранные доски.</param>
 public FavoriteBoardMainTileViewModel(BoardLinkBase link, BoardLinkCollection favorites)
 {
     if (link == null) throw new ArgumentNullException(nameof(link));
     this.link = link;
     string name = ServiceLocator.Current.GetServiceOrThrow<ILinkTransformService>().GetBoardShortName(link);
     var hash = ServiceLocator.Current.GetServiceOrThrow<ILinkHashService>().GetLinkHash(link);
     if (favorites?.BoardInfo != null)
     {
         if (favorites.BoardInfo.ContainsKey(hash))
         {
             var bi = favorites.BoardInfo[hash];
             name = bi.DisplayName;
         }
     }
     TileData = new BoardListBoardDataViewModel(link, name, "Избранные", true, false);
     UpdateId = new ThreadListUpdateId() { LinkHash = hash, SortDate = DateTime.MinValue, Link = link };
 }
 /// <summary>
 /// Клонировать.
 /// </summary>
 /// <returns>Клон.</returns>
 public override LinkCollection DeepClone()
 {
     var r = new BoardLinkCollection();
     if (Links != null)
     {
         r.Links = Links.Select(l => l?.DeepClone()).ToList();
     }
     if (BoardInfo != null)
     {
         r.BoardInfo = new Dictionary<string, FavoriteBoardInfo>();
         foreach (var kv in BoardInfo)
         {
             r.BoardInfo[kv.Key] = kv.Value?.DeepClone();
         }
     }
     return r;
 }
 private async Task<ICollection<IBoardListBoardViewModel>> GetFavorites(BoardLinkCollection linkCollection = null)
 {
     try
     {
         var result = linkCollection ?? (await ServiceLocator.Current.GetServiceOrThrow<IStorageService>().ThreadData.FavoriteBoards.LoadLinkCollectionForReadOnly()) as BoardLinkCollection;
         cachedFavorites = result;
         var resultList = new List<IBoardListBoardViewModel>();
         var linkHashService = ServiceLocator.Current.GetServiceOrThrow<ILinkHashService>();
         if (result?.Links != null)
         {
             var favInfo = result.BoardInfo;
             foreach (var l in result.Links)
             {
                 string desc = null;
                 var hash = linkHashService.GetLinkHash(l);
                 if (favInfo?.ContainsKey(hash) == true)
                 {
                     desc = favInfo[hash].DisplayName;
                 }
                 if (desc == null)
                 {
                     if (references.ContainsKey(l))
                     {
                         desc = references[l].DisplayName;
                     }
                 }
                 if (desc == null)
                 {
                     desc = "";
                 }
                 resultList.Add(new BoardListBoardDataViewModel(l, desc, "Избранные", true, false));
             }
         }
         return resultList;
     }
     catch (Exception ex)
     {
         DebugHelper.BreakOnError(ex);
         return new List<IBoardListBoardViewModel>();
     }
 }
        private async void UpdateList(ICollection<IBoardListBoardViewModel> rresult, BoardLinkCollection favorites)
        {
            var newGroups = new List<IBoardListBoardGroupingViewModel>();
            var result = (rresult ?? new List<IBoardListBoardViewModel>()).Where(i => i.Link != null).ToArray();
            cachedResult = result;
            references = result.Deduplicate(i => i.Link, linkEqualityComparer).ToDictionary(i => i.Link, linkEqualityComparer);
            var favs = await GetFavorites(favorites);
            var toResult = result.Where(r => !r.IsAdult).Concat(favs).Where(DoFilter);
            var byCat = toResult.GroupBy(i => new BoardCategoryKey(i), BoardCategoryKey.EqualityComparer);
            foreach (var gc in byCat.OrderBy(gc => gc.Key, BoardCategoryKey.Comparer).ToArray())
            {
                var g = new BoardListGroupingViewModel(gc.Key.Name, gc.Key.IsFavorite);
                foreach (var v in gc.OrderBy(v => v.Link, linkComparer).ToArray())
                {
                    g.Add(v);
                }
                newGroups.Add(g);
            }

            Groups = newGroups;

            ViewModelEvents.BoardListRefresh.RaiseEvent(this, null);
        }