如何在WPF中实现一个图片轮播,其中选定的项目始终是第一个?

7 浏览
0 Comments

如何在WPF中实现一个图片轮播,其中选定的项目始终是第一个?

我正在创建一个WPF应用程序作为视频游戏库的前端,并且我正在尝试模仿Netflix的用户界面。这个应用程序的一个功能是循环浏览游戏的图像,以选择你想玩的游戏。

期望的行为与在ListBox中通过箭头浏览项目时的行为不同:当你在ListBox中通过箭头浏览项目时,你的选择会上下移动。我希望实现的行为是,当你通过箭头浏览项目时,选定的项目始终位于第一个位置,项目在选择器上循环显示。这个术语可以称为旋转木马,其中选定的项目位于索引0。

我实现得很差,为了给出一些背景,这是我的界面当前的图片:

[我的当前实现](https://i.stack.imgur.com/XBTBl.jpg)

为了实现这个,我认为我应该扩展StackPanel类,或者可能实现自己的Panel。但是关于自定义面板的详细信息有点复杂且难以获得。我想展示一下我到目前为止所做的,以使其正常工作,但我对这些实现非常不满意,我想得到一些建议,指导我应该朝着哪个方向进行正确的实现。

以下是我尝试过的一些细节。

上面的截图是我创建的一个GameList类的结果,它实现了INotifyPropertyChanged接口,并包含了15个不同游戏的属性。

private GameMatch game0;
public GameMatch Game0
{
    get { return game0; }
    set
    {
        if (game0 != value)
        {
            game0 = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Game0"));
        }
    }
}
private GameMatch game1;
public GameMatch Game1
{
    get { return game1; }
    set
    {
        if (game1 != value)
        {
            game1 = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Game1"));
        }
    }
}
// 对于游戏2-10都是相同的代码
private GameMatch game11;
public GameMatch Game11
{
    get { return game11; }
    set
    {
        if (game11 != value)
        {
            game11 = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Game11"));
        }
    }
}
private GameMatch game12;
public GameMatch Game12
{
    get { return game12; }
    set
    {
        if (game12 != value)
        {
            game12 = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Game12"));
        }
    }
}

我在我的XAML中布置了这些图像,并添加了足够的图像,以便它们会超出屏幕的边缘:


    
        
    
    
    
    
    

我实现了一个ListCycle类,它可以接受任意列表和要循环的项目数量。为了方便起见,这是ListCycle的代码。它通过跟踪应在给定位置显示的列表项的索引来循环列表。

public class ListCycle
{
    // 游戏或其他你想要的列表
    public List GenericList { get; set; }
    // 当前可用于显示的索引
    // 将在通用列表的大小周围循环
    public int[] indices;
    public ListCycle(List genericList, int activeCycleCount)
    {
        GenericList = genericList;
        indices = new int[activeCycleCount];
        InitializeIndices();
    }
    private void InitializeIndices()
    {
        if (GenericList != null)
        {
            int lastIndex = -1;
            for (int i = 0; i < indices.Length; i++)
            {
                indices[i] = GetNextIndex(lastIndex);
                lastIndex = indices[i];
            }
        }
    }
    private int GetNextIndex(int currentIndex)
    {
        currentIndex += 1;
        if (currentIndex == GenericList.Count)
        {
            currentIndex = 0;
        }
        return currentIndex;
    }
    private int GetPreviousIndex(int currentIndex)
    {
        currentIndex -= 1;
        if (currentIndex == -1)
        {
            currentIndex = GenericList.Count - 1;
        }
        return currentIndex;
    }
    public int GetIndexValue(int index)
    {
        return indices[index];
    }
    public T GetItem(int index)
    {
        return GenericList[indices[index]];
    }
    public void CycleForward()
    {
        for (int i = 0; i < indices.Length; i++)
        {
            if (i + 1 < indices.Length - 1)
            {
                indices[i] = indices[i + 1];
            }
            else
            {
                indices[i] = GetNextIndex(indices[i]);
            }
        }
    }
    public void CycleBackward()
    {
        for (int i = indices.Length - 1; i >= 0; i--)
        {
            if(i - 1 >= 0)
            {
                indices[i] = indices[i - 1];
            }
            else
            {
                indices[i] = GetPreviousIndex(indices[i]);
            }
        }
    }
}

所以当你按右箭头时,我向前循环并重置游戏图像。当你按左箭头时,我向后循环并重置游戏图像。RefreshGames方法负责更新游戏列表中的所有这些游戏属性。

private void RefreshGames()
{
    Game0 = gameCycle.GetItem(0);
    Game1 = gameCycle.GetItem(1);
    Game2 = gameCycle.GetItem(2);
    Game3 = gameCycle.GetItem(3);
    Game4 = gameCycle.GetItem(4);
    Game5 = gameCycle.GetItem(5);
    Game6 = gameCycle.GetItem(6);
    Game7 = gameCycle.GetItem(7);
    Game8 = gameCycle.GetItem(8);
    Game9 = gameCycle.GetItem(9);
    Game10 = gameCycle.GetItem(10);
    Game11 = gameCycle.GetItem(11);
    Game12 = gameCycle.GetItem(12);
}

这种方法是可行的,但效果不好。它不够动态,不适应不同的比例,并且性能也不够好。一次浏览图像表现良好,但尝试快速浏览它们时,速度有点慢,感觉不连贯。这不是一个很好的用户体验。

我尝试了第二种方法,使用一个绑定到我的游戏列表的listbox。为了向左循环游戏,我会从游戏列表中删除第一个项目,并将其插入到列表的末尾。为了向右移动,我会删除列表末尾的项目,并将其插入到索引0处。这也可以工作,但性能也不是很好。

因此,我正在寻找关于更好实现的建议,以提供更好的性能(更流畅的滚动)并且更具动态性(即这种方法可能在超宽屏幕上效果不佳-根据图像的宽度,12个游戏可能不够)。我不是要求别人替我解决,而是指引我正确的方向,因为我对WPF非常陌生。

我认为我应该扩展stack panel类并更改浏览项目的方式,或者可能创建自己的面板。任何人都可以确认这是否是最佳方法,如果是,请指向一些帮助我理解如何创建更改导航方式的自定义面板的好资源?我一直在阅读有关创建自定义面板的文章,以试图理解该过程。

作为WPF的新手,我希望确保自己不陷入一个兔子洞或试图重新发明已经存在的轮子。所以问题是,自定义面板是否是解决这个问题的正确方法?

0