.net 如何在C# Maui中逐步更新图像

sqxo8psd  于 2023-06-07  发布在  .NET
关注(0)|答案(2)|浏览(238)

让我简单地告诉你,我对MAUI非常不精通,事实上我开始只在实验室工作中使用它。我生成一个Map,并在那里添加动物类,每个类都有一些逻辑(它工作正常,我检查)。问题是Map本身与动物的输出。每个动物类存储到图像的链接。我需要输出这些图像作为一个表格或矩阵。但当我尝试这样做时,它只输出那张卡的第一个图像,所有其他图像都被忽略,否则整个逻辑先运行一遍,然后只输出那张卡的第一个图像。我的每一个动作都要表现出某种形象。请帮帮我

形象化课堂

class Visualisation
    {
        private ObservableCollection<ObservableCollection<MyString>> _priorityMap;

        public Visualisation(List<GameObject>[,] gameModel, GamePage gamePage)
        {
            _gamePage = gamePage;
            _gameModelMap = gameModel;
            _priorityMap = new ObservableCollection<ObservableCollection<MyString>>();
            InitializePriorityMap();
        }

        private readonly List<GameObject>[,] _gameModelMap;
        private readonly GamePage _gamePage;
        private void InitializePriorityMap()
        {
            for (int i = 0; i < _gameModelMap.GetLength(0); i++)
            {
                var row = new ObservableCollection<MyString>();
                for (int j = 0; j < _gameModelMap.GetLength(1); j++)
                {
                    if (EasyVisualisation(_gameModelMap[i, j]) != null)
                        row.Add(new MyString(EasyVisualisation(_gameModelMap[i, j])));
                    else
                        row.Add(new MyString("square.png"));
                }
                _priorityMap.Add(row);
            }
        }

        private static string EasyVisualisation(List<GameObject> cell)
        {
            if (cell.Count == 0)
                return null;
            var priorityQueue = new PriorityQueue<GameObject, int>();
            foreach (var item in cell)
                priorityQueue.Enqueue(item, item.Priority);

            return priorityQueue.Dequeue().SourceImage;
        }

        async public Task AddImagesToPage()
        {
            var horisontalStackLayout = new StackLayout
            {
                Orientation = StackOrientation.Horizontal,
                BackgroundColor = new Color(255, 255, 255),
            };
            foreach (var row in _priorityMap)
            {
                var verticalStackLayout = new StackLayout
                {
                    Orientation = StackOrientation.Vertical
                };
                foreach (var item in row)
                {
                    var image = new Image
                    {
                        HeightRequest = 25,
                        WidthRequest = 25,
                        BindingContext = item.ValueString
                    };
                    image.SetBinding(Image.SourceProperty, new Binding($"."));
                    verticalStackLayout.Children.Add(image);
                }
                horisontalStackLayout.Children.Add(verticalStackLayout);
            }
            _gamePage.Content = horisontalStackLayout;

            await GenerateImageArrayAsync();
        }

        public async Task GenerateImageArrayAsync()
        {
            await Task.Run(() => UpdatePriorityMap());

        }

        private void UpdatePriorityMap()
        {
            for (int i = 0; i < _gameModelMap.GetLength(0); i++)
            {
                for (int j = 0; j < _gameModelMap.GetLength(1); j++)
                {
                    if (EasyVisualisation(_gameModelMap[i, j]) != null)
                        _priorityMap[i][j] = new MyString(EasyVisualisation(_gameModelMap[i, j]));
                    else
                        _priorityMap[i][j] = new MyString("square.png");
                }
            }
        }
    }

MyString类

public class MyString : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string _ValueString;
        public string ValueString
        {
            get { return _ValueString; }
            set { _ValueString = value; OnPropertyChanged(nameof(ValueString)); }
        }
        public MyString(string value) 
        {
            ValueString = value;
        }
        void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

游戏页面

public partial class GamePage : ContentPage
    {

        public GamePage()
        {
            InitializeComponent();
        }

        private async void StartGame(object sender, EventArgs e)
        {
            var gameModel = new GameModel();
            var simulation = new Simulation(gameModel.map);
            var visualisation = new Visualisation(gameModel.map, this);
            await visualisation.AddImagesToPage();
            simulation.Start(visualisation);    
        }
    }

开始模拟的类

class Simulation
{
    private readonly Statistics _statistics;
    public static event Action? Update;
    public delegate void AnimalsMove(List<GameObject>[,] map);
    public static event AnimalsMove? Move;
    private readonly int _delay;
    public static int MaxTurns { get; private set; }
    private List<GameObject>[,] _map;

    public Simulation(List<GameObject>[,] map)
    {
        _delay = 200;
        MaxTurns = 100;
        _statistics = new Statistics(map);
        _map = map;
    }

    public async void Start(Visualisation visualisation)
    {
        while (_statistics.TurnsCount < MaxTurns)
        {
            Update.Invoke();
            Move.Invoke(_map);
            Thread.Sleep(_delay);
            await visualisation.GenerateImageArrayAsync();
        }
    }
}

希望得到帮助:)我所需要做的就是在每一页上显示相应的图像

ui7jx7zq

ui7jx7zq1#

你已经实现了一个有趣的视图模型MyString,但是它的使用方式是错误的。

public class MyString : BindableObject
    {

        public MyString(string value)
        {
            ValueString = value;
        }

        private string _ValueString;
        public string ValueString
        {
            get
            {
                return _ValueString;
            }
            set
            {
                if (_ValueString != value)
                {
                    _ValueString = value;
                    OnPropertyChanged();
                }
            }
        }
    }

问题的发生是因为每次更新时,您都在重新创建它,而图像的bindingContext仍然设置为初始创建的图像。
所以正确的使用方法是:
1添加图片到页面:

image.SetBinding(Image.SourceProperty, new Binding($"ValueString"));

2更新优先级Map:

if (EasyVisualisation(_gameModelMap[i, j]) != null)
                            _priorityMap[i][j].ValueString = EasyVisualisation(_gameModelMap[i, j]);
                        else
                            _priorityMap[i][j].ValueString = "square.png";

代码还有其他问题超出了这个问题的范围,比如在创建初始屏幕时主线程被阻塞等等。
只是一个快速启动应用程序的快速提示:

private void StartGame(object sender, EventArgs e)
        {
            if (_gameModel == null)
            {
                _gameModel = new GameModel(); //avoid recreating if start spam-pressed multiple times
                var simulation = new Simulation(_gameModel.map);
                var visualisation = new Visualisation(_gameModel.map, this);
                visualisation.AddImagesToPage(); //runs on ui-tread inside
                Task.Run(async () =>
                {
                    while (!visualisation.MapReady) //MapReady set to true by AddImagesToPage 
                    {
                        await Task.Delay(50);
                    }
                    simulation.Start(visualisation);
                });
            }
        }

我已经创建了一个pull request for your repo with fixes https://github.com/yungsabirka/OOP_Course_Work_Animals/pull/1

ipakzgxi

ipakzgxi2#

您可以直接设置图像的Source,而不是使用Binding
如下所示:

var image = new Image
                {
                    HeightRequest = 25,
                    WidthRequest = 25,
                    BackgroundColor = Colors.Yellow,
                    //BindingContext = item.ValueString
                    Source = ImageSource.FromFile(item.ValueString)
                };

可以参考方法AddImagesToPage()的完整代码:

async public Task AddImagesToPage() 
        {
            var horisontalStackLayout = new StackLayout
            {
                Orientation = StackOrientation.Horizontal,
                BackgroundColor = new Color(255, 255, 255)
            };
            foreach (var row in _priorityMap)
            {
                var verticalStackLayout = new StackLayout
                {
                    Orientation = StackOrientation.Vertical
                };
                foreach (var item in row)
                {
                    var image = new Image
                    {
                        HeightRequest = 25,
                        WidthRequest = 25,
                        BackgroundColor = Colors.Yellow,
                        //BindingContext = item.ValueString
                        Source = ImageSource.FromFile(item.ValueString)
                    };
                    //image.SetBinding(Image.SourceProperty, new Binding($"."));
                    verticalStackLayout.Children.Add(image);
                }
                horisontalStackLayout.Children.Add(verticalStackLayout);
            }
            _gamePage.Content = horisontalStackLayout;

            //await GenerateImageArrayAsync();
        }

另外,我发现Button页面上的按钮占用了太多的空间,你可以把它放在VerticalStackLayout里面,并为它设置特殊的高度。
请参考以下代码:

<?xml version="1.0" encoding="utf-8" ?> 
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Course_Work.GamePage"
             Title="GamePage">
    <ScrollView
        Background="white">
        <VerticalStackLayout>
            <Button HeightRequest="60"
                x:Name="Start"
                Clicked="StartGame"
                FontSize="24"
                BackgroundColor="black"
                Text="Start"
                SemanticProperties.Hint="Start the game"
                HorizontalOptions="Center" 
                WidthRequest="200"/>

        </VerticalStackLayout>        
    </ScrollView>
</ContentPage>

注:

由于有很多图片要加载,所以你需要等待片刻才能加载这些图片。

相关问题