绑定观察的词典列表框项目。 [WPF-C#] [英] Bind observable dictionary to listbox items. [WPF-C#]
问题描述
我尝试绑定观察的词典列表框项目,我的问题是。如果我正常使用通用的字典,它的工作好。但是,如果使用可观察到的字典,列表框项目不会被加载。
下面是可观的字典类:
公共类MyObservableDictionary< TKEY的,TValue> :
IDictionary的< TKEY的,TValue>中
INotifyCollectionChanged,
INotifyPropertyChanged的
{
私人只读IDictionary的< TKEY的,TValue> _dictionary =新词典< TKEY的,TValue>(); INotifyCollectionChanged的#区域实施 公共事件NotifyCollectionChangedEventHandler CollectionChanged; #endregion INotifyPropertyChanged的的#区域实施 公共事件PropertyChangedEventHandler的PropertyChanged; #endregion IEnumerable的的实施的#region 公众的IEnumerator< KeyValuePair< TKEY的,TValue>>的GetEnumerator()
{
返回_dictionary.GetEnumerator();
} 的IEnumerator IEnumerable.GetEnumerator()
{
返回的GetEnumerator();
} #endregion KeyValuePair< TKEY的,TValue>的ICollection&LT的#地区实施> 公共无效添加(KeyValuePair< TKEY的,TValue>的项目)
{
_dictionary.Add(项目);
如果(CollectionChanged!= NULL)
CollectionChanged(这一点,新NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
如果(的PropertyChanged!= NULL)
{
的PropertyChanged(这一点,新PropertyChangedEventArgs(钥匙));
的PropertyChanged(这一点,新PropertyChangedEventArgs(值));
} } 公共无效清除()
{
INT keysCount = _dictionary.Keys.Count; _dictionary.Clear(); 如果(keysCount == 0)回报; 如果(CollectionChanged!= NULL)
{
CollectionChanged(这一点,新NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
} 如果(的PropertyChanged!= NULL)
{
的PropertyChanged(这一点,新PropertyChangedEventArgs(钥匙));
的PropertyChanged(这一点,新PropertyChangedEventArgs(值));
}
} 公共BOOL包含(KeyValuePair< TKEY的,TValue>的项目)
{
返回_dictionary.Contains(项目);
} 公共无效CopyTo从(KeyValuePair< TKEY的,TValue> []数组,诠释arrayIndex)
{
_dictionary.CopyTo(数组,arrayIndex);
} 公共BOOL删除(KeyValuePair< TKEY的,TValue>的项目)
{
布尔删除= _dictionary.Remove(项目); 如果返回false(删除!); 如果(CollectionChanged!= NULL)
CollectionChanged(这一点,新NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
如果(的PropertyChanged!= NULL)
{
的PropertyChanged(这一点,新PropertyChangedEventArgs(钥匙));
的PropertyChanged(这一点,新PropertyChangedEventArgs(值));
}
返回true;
} 公众诠释计数
{
{返回_dictionary.Count; }
} 公共BOOL IsReadOnly
{
{返回_dictionary.IsReadOnly; }
} #endregion TKEY的,TValue>的IDictionary&LT的#区域执行情况; 公共BOOL的containsKey(TKEY的键)
{
返回_dictionary.ContainsKey(键);
} 公共无效添加(TKEY的关键,TValue值)
{
_dictionary.Add(键,值); 如果(CollectionChanged!= NULL)
CollectionChanged(这一点,新NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
如果(的PropertyChanged!= NULL)
{
的PropertyChanged(这一点,新PropertyChangedEventArgs(钥匙));
的PropertyChanged(这一点,新PropertyChangedEventArgs(值));
}
} 公共BOOL删除(TKEY的键)
{
布尔删除= _dictionary.Remove(键); 如果返回false(删除!); 如果(CollectionChanged!= NULL)
CollectionChanged(这一点,新NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove));
如果(的PropertyChanged!= NULL)
{
的PropertyChanged(这一点,新PropertyChangedEventArgs(钥匙));
的PropertyChanged(这一点,新PropertyChangedEventArgs(值));
}
返回true;
} 公共BOOL TryGetValue(TKEY的关键,走出TValue值)
{
返回_dictionary.TryGetValue(键,超时值);
} 公共TValue这个[TKEY的关键]
{
{返回_dictionary [关键] }
组
{
布尔改变= _dictionary [关键] .Equals(值); 如果(改!)回报;
_dictionary [关键] =价值; 如果(CollectionChanged!= NULL)
CollectionChanged(这一点,新NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace)); 如果(的PropertyChanged!= NULL)
{
的PropertyChanged(这一点,新PropertyChangedEventArgs(钥匙));
的PropertyChanged(这一点,新PropertyChangedEventArgs(值));
}
}
} 公众的ICollection< TKEY的>按键
{
{返回_dictionary.Keys; }
} 公众的ICollection< TValue>值
{
{返回_dictionary.Values; }
} #endregion
}
我在法,在那里我与反序列化JSON JSON.NET对象使用这个类。
朋友类:
公共类FriendData
{
公共字符串ID用户{搞定;组; }
公共字符串尼克{搞定;组; }
公共字符串sefNick {搞定;组; }
公共字符串状态{搞定;组; }
公共字符串照片{搞定;组; }
公共字符串性爱{搞定;组; }
公共字符串isFriend {搞定;组; }
公众的BitmapImage profilePhoto {搞定;组; }
公众的ImageSource的ImageSource {搞定;组; }
公共字符串BLOCKQUOTE {搞定;组; } 公共FriendData(字符串ID用户,串缺口,串sefNick,串状态,串照片,串性别,串isFriend)
{
this.idUser = ID用户;
this.nick =缺口;
this.sefNick = sefNick;
this.status =状态;
this.photo =照片;
this.sex =性;
this.isFriend = isFriend;
}
}公共MyObservableDictionary<字符串,FriendData> LoadFriendsData2(PokecAvatar pokecAvatar)
{
//临时词典
MyObservableDictionary<字符串,FriendData>朋友; //字典,排序项
VAR sortedFriends =新MyObservableDictionary<字符串,FriendData>();
变种REQ =(HttpWebRequest的)WebRequest.Create(PokecUrl.Friends + pokecAvatar.SessionId +与& ALLDATA = 1); req.Method =GET; 使用(WebResponse类odpoved = req.GetResponse())
{
使用(VAR SM =新的StreamReader(odpoved.GetResponseStream(),pokecAvatar.EncodingType))
{
字符串htmlString = sm.ReadToEnd(); 尝试
{
VAR jsonString =新的StringBuilder();
jsonString.Append(htmlString.Replace(@\\,).Replace(@S_,M_)); //使用JSON.NET,反序列化JSON字符串
朋友= JsonConvert.DeserializeObject&所述; MyObservableDictionary&下;串,FriendData>>(jsonString.ToString()); 的foreach(在朋友的朋友VAR)
{
//获取引用
friend.Value.blockQuote = GetBlockQuote(friend.Value.nick); //没有照片
如果(friend.Value.photo ==0)
{
//人
如果(friend.Value.sex ==1)
{
//给默认的男人照片
VAR IMG =新的BitmapImage();
img.BeginInit();
img.UriSource =新的URI(@\\影像\\ ProfilePhoto \\ defaultPhotoMan.jpg,UriKind.RelativeOrAbsolute);
img.EndInit();
friend.Value.profilePhoto = IMG;
friend.Value.imageSource = IMG;
}
//女人
如果(friend.Value.sex ==2)
{
//给默认的女人照片
VAR IMG =新的BitmapImage();
img.BeginInit();
img.UriSource =新的URI(@\\影像\\ ProfilePhoto \\ defaultPhotoWoman.jpg,UriKind.RelativeOrAbsolute);
img.EndInit();
friend.Value.profilePhoto = IMG;
friend.Value.imageSource = IMG;
}
}
//有自己的照片
其他
{
VAR IMG =新的BitmapImage();
img.BeginInit();
img.UriSource =新的URI(friend.Value.photo,UriKind.Absolute);
img.EndInit();
friend.Value.profilePhoto = IMG;
friend.Value.imageSource = IMG;
} } 在dictoniary //排序项
VAR的查询= friends.OrderByDescending(F => f.Value.status).ThenBy(F => f.Value.nick); 的foreach(查询VAR keyValuePair)
{
sortedFriends.Add(keyValuePair.Key,keyValuePair.Value);
}
}
赶上(异常前)
{
扔恩;
}
}
}
返回sortedFriends;
}
和我使用的方法LoadFriendsData2的结果在我的WPF应用程序。
私人MyObservableDictionary<字符串,FriendData> _friendsData; // ... 私人无效Window_Loaded(对象发件人,RoutedEventArgs E)
{
_pokecCmd =新PokecCommands();
/ * !!!!!
问题就在这里,_friendsData是空的,如果我使用普通通用词典一切正常* /
_friendsData = _pokecCmd.LoadFriendsData2(PokecAvatar);
friendsListBox.DataContext = _friendsData;
}
XAML是在这里:
<列表框名称=friendsListBox
的ItemsSource ={结合}
的SelectedItem =密钥
风格={DynamicResource friendsListStyle}
previewMouseRightButtonUp =ListBox_ previewMouseRightButtonUp
previewMouseRightButtonDown =ListBox_ previewMouseRightButtonDown
Grid.Row =1的MouseRightButtonDown =friendsListBox_MouseRightButtonDown>
< ListBox.ItemContainerStyle>
<风格的TargetType ={X:输入一个ListBoxItem}>
< EventSetter事件=MouseDoubleClick处理器=ListBoxItem_MouseDoubleClick/>
< /样式和GT;
< /ListBox.ItemContainerStyle>
< ListBox.ContextMenu>
<文本菜单X:NAME =FriendContextMenu>
<菜单项名称=SendRp标题=PošliRP点击=FriendContextMenuItem_Click/>
<菜单项名称=SENDMSG标题=Pošlipoštu点击=FriendContextMenuItem_Click/>
< /文本菜单>
< /ListBox.ContextMenu>
< /列表框>
任何进展?我不知道什么可以是错误的,JSON.NET。
也许是这里的问题。
=朋友与JsonConvert.DeserializeObject LT; MyObservableDictionary<字符串,FriendData>>(jsonString.ToString());
请问朋友
变量(和它包含的项目)有一个非空使用后
=朋友与JsonConvert.DeserializeObject LT; MyObservableDictionary<字符串,FriendData>>(jsonString.ToString());
?
根据JSON.NET的实施,它可能是朋友
序列化为一个对象,以便它包含的属性,如计数
IsReadOnly
等,而不是像字典。
进一步阅读,请参见这里
I try bind observable dictionary to listbox item, and my problem is. If I use normal generic dictionary, it works good. But if I use observable dictionary, listbox items are not loaded.
Here is observable dictionary class:
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
}
I use this class in my method, where I deserialize JSON object with JSON.NET.
Friend class:
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;
}
And I use result of method LoadFriendsData2 in my WPF app.
private MyObservableDictionary<string, FriendData> _friendsData;
//...
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_pokecCmd = new PokecCommands();
/*!!!!! problem is here, _friendsData are null, if i use normal generic dictionary everything is OK*/ _friendsData = _pokecCmd.LoadFriendsData2(PokecAvatar);
friendsListBox.DataContext = _friendsData;
}
XAML is here:
<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>
Any advance? I dont know what can be wrong, JSON.NET. Maybe is problem here.
friends = JsonConvert.DeserializeObject<MyObservableDictionary<string, FriendData>>(jsonString.ToString());
Does the friends
variable (and the items contained in it) have a non-null after using
friends = JsonConvert.DeserializeObject<MyObservableDictionary<string, FriendData>>(jsonString.ToString());
?
Depending on the implementation of JSON.NET, it might be that friends
is serialized as an object, so that it contains properties like Count
IsReadOnly
etc, and not like a Dictionary.
for further reading, see here
这篇关于绑定观察的词典列表框项目。 [WPF-C#]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!