继续之前的大问题更新: Items.SortDescription是否会被触发INotifyPropertyChanged事件?
从另一个问题的代码:Programmatically WPF listbox.ItemsSource update,我解决了使用减慢执行速度的Items.Refres()......
但是在我开始对物品进行分类之后,又出现了问题。
正如我在其他主题中所说,我需要刷新每个更改用户的状态,但是,需要重新分组列表框中已更改的项目。
如果我循环调用Clear()函数并重新添加SortDescriptions,我会丢失输入,如鼠标和键盘问题。
一些代码:
螺纹计时器:
void StatusUpdater(object sender, EventArgs e)
{
ContactData[] contacts = ((Contacts)contactList.Resources["Contacts"]).ToArray<ContactData>();
XDocument doc = XDocument.Load("http://localhost/contact/xml/status.php");
foreach (XElement node in doc.Descendants("update"))
{
var item = contacts.Where(i => i.UserID.ToString() == node.Element("UserID").Value);
ContactData[] its = item.ToArray();
if (its.Length > 0)
{
its[0].UpdateFromXML(node);
}
}
Dispatcher.Invoke(DispatcherPriority.Normal, new Action( () => { contactList.SortAndGroup(); } ));
}
SortAndGroup()//它正在解决我的问题:
public void SortAndGroup()
{
MyListBox.Items.SortDescriptions.Clear();
MyListBox.Items.SortDescriptions.Add(new SortDescription("State", ListSortDirection.Ascending));
}
的ItemsSource:
public class Contacts : ObservableCollection<ContactData>, INotifyPropertyChanged
{
private ContactData.States _state = ContactData.States.Online | ContactData.States.Busy;
public new event PropertyChangedEventHandler PropertyChanged;
public ContactData.States Filter
{
get { return _state; }
set
{
_state = value;
NotifyPropertyChanged("Filter");
NotifyPropertyChanged("FilteredItems");
}
}
public IEnumerable<ContactData> FilteredItems
{
get { return Items.Where(o => o.State == _state || (_state & o.State) == o.State).ToArray(); }
}
public Contacts()
{
XDocument doc = XDocument.Load("http://localhost/contact/xml/contactlist.php");
foreach (ContactData data in ContactData.ParseXML(doc)) Add(data);
}
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
源数据类:
public class ContactData : INotifyPropertyChanged
{
public enum States { Online = 1, Away = 2, Busy = 4, Offline = 128 }
public event PropertyChangedEventHandler PropertyChanged;
public int UserID
{
get { return int.Parse(Data["UserID"]); }
set { Data["UserID"] = value.ToString(); NotifyPropertyChanged("UserID"); }
}
public States State
{
get { return (Data.Keys.Contains("State")) ? (States)Enum.Parse(typeof(States), Data["State"]) : States.Offline; }
set
{
Data["State"] = value.ToString();
NotifyStateChanged();
}
}
public Dictionary<string, string> Data { get; set; }
public void Set(string name, string value)
{
if (Data.Keys.Contains(name)) Data[name] = value;
else Data.Add(name, value);
NotifyPropertyChanged("Data");
}
public Color ColorState { get { return UserStateToColorState(State); } }
public Brush BrushState { get { return new SolidColorBrush(ColorState); } }
public string FullName { get { return Data["Name"] + ' ' + Data["Surname"]; } }
public System.Windows.Media.Imaging.BitmapImage Avatar
{
get
{
return Utilities.Stream.Base64ToBitmapImage(Data["Avatar"]);
}
set
{
Data["Avatar"] = Utilities.Stream.BitmapImageToBase64( value );
NotifyPropertyChanged("Avatar");
}
}
public ContactData() {}
public override string ToString()
{
try { return FullName; }
catch (Exception e) { Console.WriteLine(e.Message); return base.ToString(); }
}
Color UserStateToColorState(States state)
{
switch (state)
{
case States.Online: return Colors.LightGreen;
case States.Away: return Colors.Orange;
case States.Busy: return Colors.Red;
case States.Offline: default: return Colors.Gray;
}
}
public void UpdateFromXML(XElement xEntry)
{
var result = xEntry.Elements().ToDictionary(e => e.Name.ToString(), e => e.Value);
foreach (string key in result.Keys) if (key != "UserID")
{
if (Data.Keys.Contains(key)) Data[key] = result[key];
else Data.Add(key, result[key]);
char[] property = key.ToCharArray();
property[0] = char.ToUpper(property[0]);
NotifyPropertyChanged(new string(property));
}
}
public void NotifyStateChanged()
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("State"));
PropertyChanged(this, new PropertyChangedEventArgs("ColorState"));
PropertyChanged(this, new PropertyChangedEventArgs("BrushState"));
}
}
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
if (this.GetType().GetProperty(propertyName) != null)
{
if (propertyName != "State")
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
else NotifyStateChanged();
}
}
}
public static ContactData[] ParseXML(XDocument xmlDocument)
{
var result = from entry in xmlDocument.Descendants("contact")
select new ContactData { Data = entry.Elements().ToDictionary(e => e.Name.ToString(), e => e.Value) };
return result.ToArray<ContactData>();
}
}
答案 0 :(得分:1)
不完全确定您的问题是什么,但您可能需要在添加GroupDescription之前添加此问题。
MyListBox.Items.GroupDescriptions.Clear();
现在你添加了更有意义的周期性评论。为什么不绑定到PagedCollectionView而不是将控件分派给控件?
PagedCollectionView itemListView = new PagedCollectionView(contacts);
// Set the DataPager and ListBox to the same data source.
itemListView.SortDescriptions.Clear();
itemListView.SortDescriptions.Add(new SortDescription("State", ListSortDirection.Ascending));
MyListBox.ItemsSource=itemListView;
答案 1 :(得分:0)
使用GroupDescriptions的AFAIK就像使用ListBox一样是最快的方式,除非你想自己实现一个控件。你现在遇到性能问题吗?它应该足够快。
答案 2 :(得分:0)
如果有人需要,我会保留这个... 现在流畅了。
我终于以这种方式修复了它:
View = (ListCollectionView)CollectionViewSource.GetDefaultView(ContactData.ParseXML(doc));
View.SortDescriptions.Add(new SortDescription("State", ListSortDirection.Ascending));
View.SortDescriptions.Add(new SortDescription("FullName", ListSortDirection.Ascending));
MyListBox.ItemsSource = View.SourceCollection;
在更新帖子中:
while (IsStatusUpdateRunnig)
{
ContactData[] contacts = ((ContactData[])View.SourceCollection);//MyListBox.ItemsSource);
XDocument doc = XDocument.Load("http://localhost/contact/xml/status.php");
foreach (XElement node in doc.Descendants("update"))
{
ContactData[] its = contacts.Where(i => i.UserID.ToString() == node.Element("UserID").Value).ToArray();
if (its.Length > 0)
{
its[0].UpdateFromXML(node);
Dispatcher.Invoke(new Action(() => { View.EditItem(its[0]); }));
}
}
Dispatcher.Invoke(new Action(() => { View.CommitEdit(); }));
System.Threading.Thread.Sleep(2000);
}