Windows Phone: как получить контакт без использования задачи Contacts.SearchAsync?

Можно ли получить контакт, не используя класс Contacts и его метод SearchAsync? Я продолжаю объяснять свою проблему.

У меня есть ObservableCollection

private ObservableCollection<ContactPictureItemModel> _ContactPictures;

быть ContactPictureItemModel что-то вроде этого

public class ContactPictureItemModel
{
    private string _Email;
    private byte[] _Picture;
    private string _DisplayName;

    public ContactPictureItemModel(string email, byte[] picture, string displayName)
    {
        this._Email = email;
        this._Picture = picture;
        this._DisplayName = displayName;
    }

    public string Email
    {
        get { return _Email; }
        set { _Email = value; }
    }

    public byte[] Picture
    {
        get { return _Picture; }
        set { _Picture = value; }
    }

    public string DisplayName
    {
        get { return _DisplayName; }
        set { _DisplayName = value; }
    }
}

Каждый объект в этой ObservableCollection представляет изображение контакта, которое приложение "кэширует" каждый раз, когда пользователь выбирает контакт из EmailAddressChooserTask.

Мне нужно при вызове этого метода

public ContactPictureItemModel GetContactPictureItem(string email, string displayName)
{
    ContactPictureItemModel contactPictureResult;

    foreach (ContactPictureItemModel contact in ContactPictures)
    {
        if (email.Equals(contact.Key))
        {
            contactPictureResult = contact;
            break;
        }
    }

    if (contactPictureResult == null)
    {
        //Retrieve contact using "email" parameter
    }

    return contactPictureResult;
}

и контакт не найден в ObservableCollection, чтобы иметь возможность получить контакт с помощью параметров «email» и «displayName» без использования какой-либо асинхронной задачи. Мне нужно, чтобы функция извлекала объект ContactPictureItemModel.

Это возможно?

Спасибо!


person Alegege    schedule 24.09.2012    source источник


Ответы (2)


Синхронный доступ к контакту невозможен, так как для него нет API.

Вы можете создать модель представления в состоянии «загрузки», а затем «заполнить ее», когда завершится асинхронный метод. Просто убедитесь, что класс модели реализует INotifyPropertyChanged

person Richard Szalay    schedule 24.09.2012
comment
Я не знаю, что вы имеете в виду под состоянием загрузки. Я новичок в Windows Phone и C#. Не могли бы вы показать мне пример? - person Alegege; 25.09.2012
comment
Я просто имею в виду наличие свойства IsLoading в модели, которое начинается как true, установка его в false и заполнение других свойств при загрузке данных. - person Richard Szalay; 25.09.2012
comment
Большое спасибо! Теперь это работает. Я объясню это в новом ответе для всех, кто заинтересован. - person Alegege; 25.09.2012

Благодаря Ричарду Салаю я нашел решение. Я объясню это, чтобы помочь всем, кто, как и я, застрял в этих вопросах (извините за нотацию Java, так код короче)

Это частные поля, у которых есть объект, представляющий контакт, и его изображение.

public class ParticipantItemModel {
    private string _Email;
    private string _DisplayName;
    private bool _Paid;
    [XmlIgnore]
    private BitmapImage _ContactPicture;

    [...]
}

Каждое приватное поле имеет собственное свойство для получения и установки его значения. Как этот

    public string Email {
        get { return _Email; }
        set { _Email = value; }
    }

При работе с _ContactPicture его свойства немного особенные. Для получения его значения, если _ContactPicture имеет значение null и изображение не кэшируется в ObservableCollection, я ищу контакт с помощью задачи Contacts.SearchAsync и возвращаю «пустое изображение». Когда контакт найден (несмотря на то, что представление уже загружено), я устанавливаю свойство ContactPicture с правильным изображением, вызывая событие PropertyChangedEventArgs (как вы можете видеть в его свойстве setter)

    [XmlIgnore]
    public BitmapImage ContactPicture
    {
        get {
            if (_ContactPicture != null) {
                return _ContactPicture;
            } else {
                BitmapImage contactPictureSource = App.ContactPictures.GetContactPicture(Email, DisplayName);

                if (contactPictureSource != null) {
                    return contactPictureSource;
                } else {
                    Contacts contacts = new Contacts();
                    contacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contacts_SearchCompleted);
                    contacts.SearchAsync(DisplayName, FilterKind.DisplayName, Email);

                    return new BitmapImage();
                }
            }
        }

        set {
            _ContactPicture = value;
            //When _ContactPicture is setted, an event is raised by calling to NotifyPropertyChanged()
            NotifyPropertyChanged("ContactPicture");
        }
    }

    void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e) {
        Contact contact = null;

        foreach (var result in e.Results) {
            foreach (ContactEmailAddress contactEmail in result.EmailAddresses) {
                if (Email.Equals(contactEmail.EmailAddress)) {
                    contact = result;
                    this.ContactPicture = GetSourceImageFromContactPicture(contact.GetPicture());
                    break;
                }
            }
        }
    }        
}

Кроме того, должен быть реализован интерфейс INotifyPropertyChanged, чтобы вызвать событие PropertyChangedEventArgs. Это событие сообщит приложению, что элемент (изображение контакта) изменился, и оно обновится с использованием привязанных данных.

public class ParticipantItemModel : INotifyPropertyChanged {

    [...]

    // Declare the PropertyChanged event
    public event PropertyChangedEventHandler PropertyChanged;

    // NotifyPropertyChanged will raise the PropertyChanged event passing the
    // source property that is being updated.
    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

В результате контакт показывается без картинки, но почти автоматически картинка подгружается.

Я надеюсь, что это было полезно

person Alegege    schedule 25.09.2012