Надгробие MVVM-Light и WP7 ViewModel не работает

Я попытался выполнить действия, описанные в статье Джуста Ван Шайка о захоронении надгробий но не смог заставить его работать на меня. Я не сомневаюсь, что делаю что-то не так. В моей ViewModel:

private string _foobar ="init";

public string testStr
{
    get
    {
        return _foobar;
    }

    set
    {
        _foobar = value;
    }
}

И на моей странице:

<TextBox x:Name="tBoxTest" Text="{Binding testStr, Mode=TwoWay}" />

Пока приложение работает, изменение значения в tBoxTest устанавливает _foobar просто отлично, но попробуйте его сериализовать, а оно как будто забыло экземпляр??? Любая помощь будет принята с благодарностью.


person Stonetip    schedule 02.02.2011    source источник
comment
Вы показали код для своего свойства, который выглядит нормально, но реализовали ли вы остальную часть решения для фактической сериализации и десериализации экземпляра вашей модели представления соответственно в событиях Activated и Deactivated?   -  person Derek Lakin    schedule 02.02.2011
comment
Да, у меня есть. Я должен был четко указать это в этом посте. Я пытался сосредоточиться на одной проблемной области.   -  person Stonetip    schedule 02.02.2011


Ответы (2)


Мне удалось заставить работать захоронение, а также сделать объект видимым для всех моих ViewModels, выполнив следующие действия:

В классе Model я добавил:

private static Model1 _instance;
public static Model1 Instance
{
    get { return _instance; }
    set { _instance = value; }
}

public static void CreateNew()
{
    if (_instance == null)
    {
        _instance = new Model1();

        _instance.FirstString = "init";
    }
}

Затем в ApplicationExtensions.cs я добавил:

  public static void SaveToIsolatedStorage(this Application app, Model1 model)
    {
        var dataFileName = GetIsFile((model.GetType()));
        using (var userAppStore =
                 IsolatedStorageFile.GetUserStoreForApplication())
        {
            if (userAppStore.FileExists(dataFileName))
            {
                userAppStore.DeleteFile(dataFileName);
            }
            using (var iss = userAppStore.CreateFile(dataFileName))
            {
                SilverlightSerializer.Serialize(model, iss);
            }
        }
    }

И в App.xaml.cs я изменил LoadModel() на:

private void LoadModel()
{
    try
    {
        Model1.Instance = this.RetrieveFromIsolatedStorage<Model1>();
    }
    catch (Exception) { }

    if (Model1.Instance == null) Model1.CreateNew();
}

Все это заставило такие вещи работать в моих файлах ViewModel:

public string TestStr
{
    get
    {
        return Model1.Instance.FirstString;
    }

    set
    {
        Model1.Instance.FirstString = value;
    }
}

Под этим я подразумеваю, что объект Model1 сериализуется, а захоронение работает — по крайней мере, я получаю то, что, как я думаю, хочу. Я много раз проверял это, перемещаясь между приложениями, настройками телефона, включая и выключая телефон, блокируя его и вызывая его, находясь в приложении с другого телефона. Производительность при десериализации отличная. И я могу работать с варами.

Тем не менее, г-н Ван Шайк ответил на просьбу о помощи следующим образом: "Если вы создаете подклассы из MVVMLight ViewModelBase, это так, и тогда вам следует вызвать RaisePropertyChanged из вашего установщика следующим образом:

частная строка _foobar ="init";

публичная строка TestStr {получить {return _foobar; }

    set
    {
         RaisePropertyChanged("TestStr");
        _foobar = value;
    }
}

RaisePropertyChanged уведомляет все представления прослушивания (т. е. связанное с ним текстовое поле) об изменении свойства и необходимости обновления их содержимого. Это важнейший механизм."

Так что я буду работать с тем, что я изначально пытался, но с добавлением RaisePropertyChanged, чтобы увидеть, что это делает.

ОБНОВЛЕНИЕ

Хотя я реализовал RaisedPropertyChanged (используя фрагмент кода mvvminpc) в моем файле MainViewModel.cs, это все равно не оказало никакого влияния (насколько это может быть полезно для других вещей) на сериализацию всего, что создано в ViewModel. Вероятно, я все еще делаю что-то не так, но это также может быть связано с тем, что модели просмотра наследуются от защищенного класса (ответ от Лорана Бюньона). Я (очень неохотно) попытался изменить этот класс с защищенного на общедоступный и перекомпилировать, но в моем случае это не помогло, и я ненавижу разветвлять такую ​​библиотеку, на которую ссылаются. В любом случае, пока я просто продвигаюсь вперед с созданием экземпляра Model1 в App.xaml.cs. Кажется, работает. Пока я занимался этим, я модифицировал один из методов Ван Шайка, чтобы он принимал объекты любого типа:

public static void SaveToIsolatedStorage<T>(this Application app, T obj)
where T : class
{
    var dataFileName = GetIsFile(typeof(T));
    using (var userAppStore =
                IsolatedStorageFile.GetUserStoreForApplication())
    {
        if (userAppStore.FileExists(dataFileName))
        {
            userAppStore.DeleteFile(dataFileName);
        }
        using (var iss = userAppStore.CreateFile(dataFileName))
        {
            SilverlightSerializer.Serialize(obj, iss);
        }
    }
}
person Stonetip    schedule 02.02.2011

Из кода, который вы разместили, нет мгновенного ответа.

Мой совет по отладке:

  • если вы скопировали код именно из этой статьи, добавьте что-нибудь (окно сообщения?) в пустой обработчик catch — `catch (Exception){ }

  • используйте отладчик для установки точек останова в методах LoadModel и SaveToIsolatedStorage.

  • используйте эти точки останова для пошагового выполнения кода загрузки и сохранения. Правильно ли загружается и сохраняется код?

Честно говоря, с такими проблемами гораздо лучше провести небольшое расследование самостоятельно, чем задавать вопросы здесь (ИМХО!)

person Stuart    schedule 02.02.2011
comment
Я новичок в размещении сообщений на Stack Overflow, поэтому позвольте мне просто упомянуть, что я никогда не буду публиковать вопрос, пока не перепробую все остальное. Я сделал все, что упомянуто выше, погуглил, загрузил и просмотрел 6 найденных образцов. Я даже подумывал о переходе на Caliburn Micro, так как у него было решение. Но мне нравится MVVM-Light, и я уже потратил на него время. Публикуя только этот код, я предполагал, что кто-то другой сделал бы все шаги, описанные в статье. Прочитайте сообщение ниже для одного решения и дальнейшего расследования с моей стороны. - person Stonetip; 02.02.2011
comment
Я думаю, это будет пост выше, где я дал ответ. (Вместо того, чтобы просто добавить к моему исходному сообщению, я решил ответить на него, потому что это решение проблемы. - person Stonetip; 02.02.2011
comment
Круто - я тоже новичок - просто подумал, что в этом случае лучший совет - поставить несколько точек останова, чтобы определить, где что-то идет не так. Надеюсь совет помог. - person Stuart; 02.02.2011
comment
Извините, не хотел вас обижать. На самом деле, я очень ценю ваш ответ на мой предыдущий вопрос. - person Stonetip; 02.02.2011