将可观察字典绑定到列表框项目。 [WPF-C#]

时间:2010-11-05 19:04:27

标签: wpf dictionary binding json.net observable

我尝试将可观察字典绑定到列表框项目,我的问题是。如果我使用普通的通用字典,它的效果很好。但是如果我使用可观察的字典,则不会加载列表框项。

这是可观察的字典类:

public class MyObservableDictionary<TKey, TValue> :
    IDictionary<TKey, TValue>,
    INotifyCollectionChanged,
    INotifyPropertyChanged
{
    private readonly IDictionary<TKey, TValue> _dictionary = new Dictionary<TKey, TValue>();

    #region Implementation of INotifyCollectionChanged

    public event NotifyCollectionChangedEventHandler CollectionChanged;

    #endregion

    #region Implementation of INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    #region Implementation of IEnumerable

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return _dictionary.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    #endregion

    #region Implementation of ICollection<KeyValuePair<TKey,TValue>>

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        _dictionary.Add(item);
        if (CollectionChanged != null)
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("Keys"));
            PropertyChanged(this, new PropertyChangedEventArgs("Values"));
        }

    }

    public void Clear()
    {
        int keysCount = _dictionary.Keys.Count;

        _dictionary.Clear();

        if (keysCount == 0) return;

        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("Keys"));
            PropertyChanged(this, new PropertyChangedEventArgs("Values"));
        }
    }

    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        return _dictionary.Contains(item);
    }

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        _dictionary.CopyTo(array, arrayIndex);
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        bool remove = _dictionary.Remove(item);

        if (!remove) return false;

        if (CollectionChanged != null)
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("Keys"));
            PropertyChanged(this, new PropertyChangedEventArgs("Value"));
        }
        return true;
    }

    public int Count
    {
        get { return _dictionary.Count; }
    }

    public bool IsReadOnly
    {
        get { return _dictionary.IsReadOnly; }
    }

    #endregion

    #region Implementation of IDictionary<TKey,TValue>

    public bool ContainsKey(TKey key)
    {
        return _dictionary.ContainsKey(key);
    }

    public void Add(TKey key, TValue value)
    {
        _dictionary.Add(key, value);

        if (CollectionChanged != null)
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("Keys"));
            PropertyChanged(this, new PropertyChangedEventArgs("Values"));
        }
    }

    public bool Remove(TKey key)
    {
        bool remove = _dictionary.Remove(key);

        if (!remove) return false;

        if (CollectionChanged != null)
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs("Keys"));
            PropertyChanged(this, new PropertyChangedEventArgs("Values"));
        }
        return true;
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        return _dictionary.TryGetValue(key, out value);
    }

    public TValue this[TKey key]
    {
        get { return _dictionary[key]; }
        set
        {
            bool changed = _dictionary[key].Equals(value);

            if (!changed) return;
            _dictionary[key] = value;

            if (CollectionChanged != null)
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace));

            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Keys"));
                PropertyChanged(this, new PropertyChangedEventArgs("Values"));
            }
        }
    }

    public ICollection<TKey> Keys
    {
        get { return _dictionary.Keys; }
    }

    public ICollection<TValue> Values
    {
        get { return _dictionary.Values; }
    }

    #endregion
}

我在我的方法中使用这个类,我用JSON.NET反序列化JSON对象。

朋友班:

public class FriendData
{
    public string idUser { get; set; }
    public string nick { get; set; }
    public string sefNick { get; set; }
    public string status { get; set; }
    public string photo { get; set; }
    public string sex { get; set; }
    public string isFriend { get; set; }
    public BitmapImage profilePhoto { get; set; }
    public ImageSource imageSource { get; set; }
    public string blockQuote { get; set; }

    public FriendData(string idUser, string nick, string sefNick, string status, string photo, string sex, string isFriend)
    {
        this.idUser = idUser;
        this.nick = nick;
        this.sefNick = sefNick;
        this.status = status;
        this.photo = photo;
        this.sex = sex;
        this.isFriend = isFriend;
    }
}

public MyObservableDictionary<string, FriendData> LoadFriendsData2(PokecAvatar pokecAvatar)
{
    //temp dictionary
    MyObservableDictionary<string, FriendData> friends;

    //dictionary with sorted item
    var sortedFriends = new MyObservableDictionary<string, FriendData>();


    var req = (HttpWebRequest)WebRequest.Create(PokecUrl.Friends + pokecAvatar.SessionId + "&allData=1");

    req.Method = "GET";

    using (WebResponse odpoved = req.GetResponse())
    {
        using (var sm = new StreamReader(odpoved.GetResponseStream(), pokecAvatar.EncodingType))
        {
            string htmlString = sm.ReadToEnd();

            try
            {
                var jsonString = new StringBuilder();
                jsonString.Append(htmlString.Replace(@"\", "").Replace(@"s_", "m_"));

                //using JSON.NET, deserialize JSON string
                friends = JsonConvert.DeserializeObject<MyObservableDictionary<string, FriendData>>(jsonString.ToString());

                foreach (var friend in friends)
                {
                    //get citation
                    friend.Value.blockQuote = GetBlockQuote(friend.Value.nick);

                    //don’t have a foto
                    if (friend.Value.photo == "0")
                    {
                        //man
                        if (friend.Value.sex == "1")
                        {
                            //give  default man photo
                            var img = new BitmapImage();
                            img.BeginInit();
                            img.UriSource = new Uri(@"\Images\ProfilePhoto\defaultPhotoMan.jpg", UriKind.RelativeOrAbsolute);
                            img.EndInit();
                            friend.Value.profilePhoto = img;
                            friend.Value.imageSource = img;  
                        }
                        //woman
                        if (friend.Value.sex == "2")
                        {
                            //give default woman photo
                            var img = new BitmapImage();
                            img.BeginInit();
                            img.UriSource = new Uri(@"\Images\ProfilePhoto\defaultPhotoWoman.jpg", UriKind.RelativeOrAbsolute);
                            img.EndInit();
                            friend.Value.profilePhoto = img;
                            friend.Value.imageSource = img; 
                        }
                    }
                    //have own photo
                    else
                    {
                        var img = new BitmapImage();
                        img.BeginInit();
                        img.UriSource = new Uri(friend.Value.photo, UriKind.Absolute);
                        img.EndInit();
                        friend.Value.profilePhoto = img;
                        friend.Value.imageSource = img;
                    }

                }

                //sort item in dictoniary
                var query = friends.OrderByDescending(f => f.Value.status).ThenBy(f => f.Value.nick);

                foreach (var keyValuePair in query)
                {
                    sortedFriends.Add(keyValuePair.Key, keyValuePair.Value);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
    return sortedFriends;
}

我在我的WPF应用程序中使用方法LoadFriendsData2的结果。

    private MyObservableDictionary<string, FriendData> _friendsData;

    //...

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        _pokecCmd = new PokecCommands();

/ * !!!!! 问题在这里,_friendsData为null,如果我使用普通的通用字典一切正常* /             _friendsData = _pokecCmd.LoadFriendsData2(PokecAvatar);

        friendsListBox.DataContext = _friendsData;
    }

XAML在这里:

    <ListBox Name="friendsListBox" 
             ItemsSource="{Binding}" 
             SelectedItem="Key"
             Style="{DynamicResource friendsListStyle}"
             PreviewMouseRightButtonUp="ListBox_PreviewMouseRightButtonUp"
             PreviewMouseRightButtonDown="ListBox_PreviewMouseRightButtonDown" 
             Grid.Row="1" MouseRightButtonDown="friendsListBox_MouseRightButtonDown">
            <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_MouseDoubleClick"/>
            </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ContextMenu>
                 <ContextMenu x:Name="FriendContextMenu">
                <MenuItem Name="SendRp" Header="Pošli Rp" Click="FriendContextMenuItem_Click" />
                <MenuItem Name="SendMsg" Header="Pošli poštu" Click="FriendContextMenuItem_Click"/>
            </ContextMenu>
            </ListBox.ContextMenu>
        </ListBox>

任何进展?我不知道什么是错的,JSON.NET。 也许这里有问题。

friends = JsonConvert.DeserializeObject<MyObservableDictionary<string, FriendData>>(jsonString.ToString());

2 个答案:

答案 0 :(得分:2)

friends变量(及其中包含的项)在使用后是否为非空

friends = JsonConvert.DeserializeObject<MyObservableDictionary<string, FriendData>>(jsonString.ToString());

? 根据JSON.NET的实现,可能会将friends序列化为对象,因此它包含Count IsReadOnly等属性,而不是像Dictionary。 如需进一步阅读,请参阅here

答案 1 :(得分:0)

如果您将绑定更改为

,该怎么办?
ItemsSource="{Binding Path=Keys}"