2

Имею List<Class>, который раз в N минут обновляется путем десериализации JSON файла, у коллекции реализован INotifyPropertyChanged для грамотного привязывания к этой коллекции интерфейса. А также есть некий эвент, который оповещает о добавление в эту коллекцию нового значения.

После того, как в коллекцию добавляется новое значение, мне нужно выполнить несколько операций: Для начала мне надо пройтись по 2-ум значениям в коллекции и выяснить, не пустые ли они, а дальше, нужно отдельно созданной переменной (которая изначально пуста) задать то значение, которое не пустое.

То есть другими словами у меня есть в коллекции все события, у событий есть предмет, но предмет может находится в двух разных местах в JSON файле, узнаем в каком месте значение не NULL и выводим его и его кол-во в отдельную переменную Reward.

НО значение имеет не читаемый для пользователя формат (/DAF/FAFWF/FQFQ), для решения этой задачи мне пришлось создавать список фильтров (JSON файл в формате "значение": "перевод" и небольшую функцию, которая находит в файле нужное значение и отдает перевод.

Всю логику я вроде сделал как надо, все работает на ура! Но после первого же обновления, моя переменная в которую я заносил необходимые мне данные становится попросту пустой. Тут дело понятное, коллекция вроде обновляется, обновляются и данные, но как быть, если мне нужно сохранить подобные переменные без выполнения заново всего кода по "переводу"? Я пытался задать private static string переменную в модели, в которую я с помощью set задаю значение, а с помощью get получаю его и вывожу, если не пустое. Но такой способ сохранил только 1 значение и задал его для всей коллекции сразу. Собственно как быть?


Код чтения данных из JSON с реализацией INotifyPropertyChanged из этого примера

internal class Game : VM
{
    private static GameView Read(string fileName)
    {
        GameView data;
        using (var file = File.OpenText(fileName))
        {
            var serializer = new JsonSerializer();
            data = (GameView) serializer.Deserialize(file, typeof(GameView));
        }

        return data;
    }

    GameView data;
    public GameView Data { get => data; set => Set(ref data, value); }

    public void Load(string filename = "temp")
    {
        if (filename == "temp")
            filename = $"{Settings.Program.Directories.Temp}/GameData.json";
        Data = Read(filename);
    }
}

Класс, который содержит коллекцию Alerts

public class GameView : VM
{
    int version;
    public int Version
    {
        get => version;
        set => Set(ref version, value);
    }

    // ...

    ObservableCollection<Alert> alerts;
    public ObservableCollection<Alert> Alerts
    {
        get => alerts;
        set => Set(ref alerts, value);
    }

    // ...
}

Класс Alerts:

public class Alert : VM
{
    [JsonProperty("_id")]
    public Id Id { get; set; }

    public Activation Activation { get; set; }
    public Expiry Expiry { get; set; }
    public MissionInfo MissionInfo { get; set; }
}

Ну и собственно класс MissionInfo, в котором есть переменная Reward

public class MissionInfo : VM
{
    public MissionReward MissionReward { get; set; }


    private string _reward;
    public string Reward
    {
        get => _reward;
        set => Set(ref _reward, value);
    }

}

public class MissionReward
{
    public int Credits { get; set; }
    public List<CountedItem> CountedItems { get; set; }
    public List<string> Items { get; set; }
}

Дальше я не буду описывать, как именно идет отслеживание добавления нового элемента (ибо это еще добавит кучу строк в вопрос и я считаю это избыточным). Кому интересно, можно почитать в ответе тут.

Я опишу только мой набросок того, как я изменяю значение Reward при срабатывание эвента:

private void NotificationWatcherwatcherOnAlertNotificationArrived(object sender,
            NewAlertNotificationEventArgs e)
        {
            var ntfVm = new NotificationViewModel(e.Notification);
            Debug.WriteLine("Новая тревога найдена!", ntfVm.Text);
            var alert = GameData.Data.Alerts.Single(cc => cc.Id.Oid == ntfVm.Id);

            Debug.WriteLine($"Переводим значение {ntfVm.Text}!", $"[{DateTime.Now}]");
            try
            {
                string revardValue = "Нет награды.";
                if (alert.MissionInfo.MissionReward.CountedItems != null)
                {
                    revardValue = $"{FiltersViewModel.Items.Find(alert.MissionInfo.MissionReward.CountedItems[0].ItemType, DataBase)} [{alert.MissionInfo.MissionReward.CountedItems[0].ItemCount}]";
                }
                else if (alert.MissionInfo.MissionReward.Items != null)
                {
                    revardValue = FiltersViewModel.Items.Find(alert.MissionInfo.MissionReward.Items[0], DataBase);
                }
                alert.MissionInfo.Reward = revardValue;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }

Собственно видно, что я смотрю, пустые ли коллекции alert.MissionInfo.MissionReward.CountedItems и alert.MissionInfo.MissionReward.Items, если одна из них не пуста, то alert.MissionInfo.Reward присваиваю значение из этой коллекции, если пуста - выдается "Награды нет". Собственно задает все как надо, но из за того, что периодически выполняется подгрузка значений (самый первый код) - коллекция сбрасывает все изменения к изначальному и заданный Reward становится пустым.

EvgeniyZ
  • 15,694
  • 1
    Отличное описание, но вы забыли добавить сам код. – Nikita Jun 22 '17 at 00:12
  • 1
    Без кода тут делать нечего. Если хотите отправлять нас искать ваш код в других вопросах, то ищите сами ответы тут https://msdn.microsoft.com , как задавать вопросы описано здесь https://ru.stackoverflow.com/help/mcve – tym32167 Jun 22 '17 at 08:09
  • @tym32167: Уважаемый, вы сначала посмотрите ссылки выше, там весь нужный код представлен со всей структурой. Да и вообще эту проблему можно воспроизвести простым привязыванием коллекции к интерфейсу, которая время от времени будет заново подгружаться, в этой коллекции любое значение поменяйте и после очередного обновления посмотрите, будет ли у вас значение стандартное или то, что вы указали... Повторюсь, весь необходимый код находится в ссылках выше, даже нечего лишнего, именно те части кода, которые необходимы в этом вопросе. – EvgeniyZ Jun 22 '17 at 12:56
  • 2
    @EvgeniyZ Вопрос должен быть самодостаточным. Я (да и никто другой) не буду ходить в другие вопросы, копипастить примеры, чтобы только воспроизвести вашу проблему. Это ваша задача - задать вопрос так, чтобы максимально облегчить жизнь человеку, который вам хочет помочь. Раз вы не хотите этого делать, то и помогать вам желания нет. Не хочу вас оскорбить, просто пояснил как оно есть. – tym32167 Jun 22 '17 at 14:04
  • @tym32167: Хорошо, дополнил вопрос частью кода. – EvgeniyZ Jun 22 '17 at 15:16
  • Я правильно понял, что вы 1) загружаете данные из файла 2) меняете данные 3) снова грузите из из файла и изменения пропадают? Зачем одно и то же загружать несколько раз? Если надо сохранить изменения состояния, почему бы не сохранить его в файл вместо того, чтобы загружать из файла предыдущее состояние? – tym32167 Jun 22 '17 at 15:29
  • @tym32167 Файл читается с сервера и мне нужна постоянно его актуальная версия. То есть это по сути чтение API игры, которая раз в пару минут обновляет данные на своем сайте. – EvgeniyZ Jun 22 '17 at 15:36
  • В таком случае нет смысла заполнять alert.MissionInfo.Reward, а лучше хранить вычисленные значения отдельно в собственной структуре данных (например, в Dictionary<Ид алерта, revardValue>) – tym32167 Jun 22 '17 at 15:42
  • Ну это получается создавать еще одну "коллекцию", что бы там хранить еще данные, как то не рационально мне кажется, да и эта структура как минимум еще в нескольких местах будет использоваться (что в итоге может сильно разрастись..) – EvgeniyZ Jun 22 '17 at 15:46
  • 1
    В идеале у вас должна быть своя модель игры со своей логикой. Те данные, что вы грузите с сервера - они не должны пересекаться с данными, что вы сами посчитали. И все это вместе должно лежать в вашей модели. А сейчас они у вас пересекаются и перезаписывают друг друга - от того и проблемы – tym32167 Jun 22 '17 at 15:50
  • Хорошо, а если без идеала и без создания доп. коллекций? Не уж то нету какого нибудь способа сохранения переменное, если скажем она не пуста? – EvgeniyZ Jun 22 '17 at 16:30
  • Не понял вопроса. У вас есть данные. Вы хотите их сохранить. Для этого по любому нужно какое то место, куда сохранить - будь то дополнительные переменные, файл, база данных, удаленный сервис - выбирайте любой способ. Но, очевидно, что без сохранения переменных, вы из никак не восстановите, только если заново вычислите. – tym32167 Jun 22 '17 at 20:50
  • @tym32167 Вы меня не поняли, мне интересен вариант, где не создается List, Dictionary и любая другая коллекция, хочется переменную в которой будет это сохранено. Без разделения данных (сервер, программа) и без коллекций, есть еще способы? – EvgeniyZ Jun 23 '17 at 00:57
  • Я не понял вашу терминологию. Переменная может указывать на коллекцию. Если вы противитесь делать как лучше, есть другое простое и крайне неверное решение - в момент, когда вы считываете новые данные с сервиса, сохранять ссылку на старые денные и обновлять Reward в новой модели данными со старой модели. – tym32167 Jun 23 '17 at 10:05
  • Я правильно понимаю проблему: у вас есть данные из сети (JSON), плюс иногда вы модифицируете их ещё и локально? – VladD Jun 24 '17 at 10:31
  • @VladD Да, сейчас работает именно так. Сейчас вот хочу переделать так: После каждого обновления данных на сервере, программа будет следить и вызывать необходимый эвент (то, что вы мне помогли реализовать), далее этот эвент добавляет в отдельную коллекцию (которая будет привязана к интерфейсу) необходимые данные, а по событию удаления данных с сервера - значение из базы по Id будет удалятся. Другого варианта я пока не придумал) – EvgeniyZ Jun 24 '17 at 13:24
  • @EvgeniyZ: Что у вас в конечном итоге? Проблема решилась? – VladD Jul 09 '17 at 20:36
  • @VladD К сожалению я еще не реализовывал разделение. На данный момент для проекта потребовался сервер с API - реализовываю его. После - начну разделение серверных данных и данных, что видит пользователь. Думаю тут проблем не возникнет и это решит мою задачу. – EvgeniyZ Jul 10 '17 at 09:16
  • @VladD Реализовал я подобное, добавляет, оповещает - все как надо. Но вот незадача, в одном списке (который у меня чисто данные с сервера содержит) есть переменная, которая периодически обновляются, а из за того, что я делаю по эвенту добавление в новый List, который привязывается к интерфейсу - эта переменная у меня естественно остается неизменная. Не подскажете как можно обновить список, локальных данных из данных в листе, который серверный? – EvgeniyZ Jul 18 '17 at 17:25
  • @EvgeniyZ: А можно посмотреть на код? – VladD Jul 18 '17 at 17:27
  • @VladD А я все делаю по тому же принципу, что Вы мне и написали здесь, только в коде, который вызывается эвентом (в этом вопросе он NotificationWatcherwatcherOnAlertNotificationArrived) есть Application.Current.Dispatcher?.InvokeAsync(() => { if (MainWindow.GameView.Alerts == null) MainWindow.GameView.Alerts = new ObservableCollection<Alert>(); MainWindow.GameView.Alerts.Add(e.Notification); }); – EvgeniyZ Jul 18 '17 at 17:36
  • @EvgeniyZ: Окей, попробую посмотреть. – VladD Jul 18 '17 at 19:26
  • @VladD Есть успехи? – EvgeniyZ Jul 19 '17 at 23:31
  • @EvgeniyZ: Сорри, прикатило много работы. Я обязательно посмотрю! – VladD Jul 20 '17 at 10:57
  • @VladD Да нечего, не "горит" скажем так, главное не забудьте ;-) А то я гляжу, вроде Вы отвечаете в других вопросах, а этот вопрос как то стороной избегаете) – EvgeniyZ Jul 20 '17 at 10:59
  • @EvgeniyZ: Ну, ваш вопрос сложнее, поэтому... – VladD Jul 20 '17 at 11:03
  • @VladD Я понял, без проблем. – EvgeniyZ Jul 20 '17 at 11:04
  • @EvgeniyZ: Приходите лучше сюда: https://chat.stackexchange.com/rooms/62616/, в комментариях обсуждать сложно. – VladD Jul 21 '17 at 21:52
  • @VladD Я через пару дней продолжу работу над проектом, ты как? Готов к дальнейшему обучению азам программирования?) P.S. Не как связаться не смог с тобой после блокировки чата... – EvgeniyZ Oct 12 '17 at 18:03
  • @VladD Ок, тогда жду новостей в том чате. Там и спишемся! – EvgeniyZ Oct 12 '17 at 19:12

0 Answers0