I’m experiencing a problem with the longlistselector witch is a bit strange... I’m reading a list asynchronously on a multi Pivot page, and if I don’t change the pivot until the resulto f the list Reading, it will create the contacts list successfuly ( in a longlistselector on the pivot item number 3 ) and when I go to that pivot the contacts list is displayed withou any problems, but when I open the Page and change the pivot before the longlistselector is created when the asychronous function returns the results and fills the longlistselector on pivot no.3 the contacts wont get updated ( when I go to pivot 3 no contacts are shown)...
I’ll post my code so you can have a clearer picture of the situation and maybe figure out what is happening.
The code is based in the PhoneToolkit LongListSelector example (buddies list)
public partial class Feeds : PhoneApplicationPage
{
bool isLoading = false;
bool loadingFilmates = true;
public Feeds()
{
InitializeComponent();
// ...
Loaded += FeedsPage_Loaded;
SystemTray.ProgressIndicator = new ProgressIndicator();
DataContext = this;
getFilmatesList();
longlistFilmates.SelectionChanged += FilmateSelectionChanged;
// ...
}
private async void getFilmatesList()
{
Feed userFilmates = await Feed.GetFilmates(App.Current.AppUser, App.Current.WSConfig, 0, "", 10000); // read feeds from webservice
Filmates = AlphaKeyGroup<StayObjectFilmates>.CreateGroups(AllFilmates.GetCurrent(userFilmates), CultureInfo.CurrentUICulture, (p) => { return p.Name; }, true);
//longlistFilmates.Visibility = System.Windows.Visibility.Collapsed;
longlistFilmates.Visibility = System.Windows.Visibility.Visible;
longlistFilmates.UseLayoutRounding = true;
pivotFeed.Visibility = System.Windows.Visibility.Collapsed;
pivotFeed.Visibility = System.Windows.Visibility.Visible;
}
}
Notice that I’ve even tried changing the Visibility property when it loads to force a re-render on the screen and it didn’t work.
This is the StayObjectFilmates class:
public class StayObjectFilmates
{
public string Img { get; private set; }
public string Name { get; private set; }
public string UserId { get; private set; }
public string Id { get; set; }
public User user { get; set; }
public StayObjectFilmates()
{
//Img = "";
//Name = "";
//Id = "";
}
public StayObjectFilmates(string p_img, string p_name, string p_Id)
{
Img = p_img;
Name = p_name;
UserId = p_Id;
}
public StayObjectFilmates(User p_user)
{
user = p_user;
}
public static string GetNameKey(StayObjectFilmates filmate)
{
char key = char.ToLower(filmate.Name[0]);
if (key < 'a' || key > 'z')
{
key = '#';
}
return key.ToString();
}
public static int CompareByName(object obj1, object obj2)
{
StayObjectFilmates p1 = (StayObjectFilmates)obj1;
StayObjectFilmates p2 = (StayObjectFilmates)obj2;
int result = p1.Name.CompareTo(p2.Name);
if (result == 0)
{
result = p1.Img.CompareTo(p2.Img);
}
return result;
}
}
This is the AllFilmates class:
public class AllFilmates : IEnumerable<StayObjectFilmates>
{
private static Dictionary<int, StayObjectFilmates> _filmateLookup;
private static AllFilmates _instance;
private Feed filmates;
// public List<StayObjectFilmates> Filmates { get; private set; }
public static AllFilmates GetCurrent(Feed p_filmates)
{
if (_instance == null)
{
_instance = new AllFilmates();
}
_instance.filmates = p_filmates;
return _instance;
}
public static AllFilmates Current
{
get
{
return _instance ?? (_instance = new AllFilmates());
}
}
public StayObjectFilmates this[int index]
{
get
{
StayObjectFilmates filmate;
_filmateLookup.TryGetValue(index, out filmate);
return filmate;
}
}
#region IEnumerable<StayObjectFilmates> Members
public IEnumerator<StayObjectFilmates> GetEnumerator()
{
EnsureData();
return _filmateLookup.Values.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
EnsureData();
return _filmateLookup.Values.GetEnumerator();
}
#endregion
private void EnsureData()
{
if (_filmateLookup == null)
{
_filmateLookup = new Dictionary<int, StayObjectFilmates>();
if (filmates != null)
{
int i = 0;
foreach (var item in filmates.itemsList)
{
User friend = item as User;
string userphoto = (friend.photo == null) ? "Images/avatar.jpg" : friend.photo;
StayObjectFilmates f = new StayObjectFilmates(userphoto, friend.fullName, i.ToString());
_filmateLookup[i] = f;
i++;
}
}
}
}
}
And this is the AlphaKeyGroup.cs file :
public class AlphaKeyGroup<T> : List<T>
{
private const string GlobeGroupKey = "\uD83C\uDF10";
/// <summary>
/// The delegate that is used to get the key information.
/// </summary>
/// <param name="item">An object of type T</param>
/// <returns>The key value to use for this object</returns>
public delegate string GetKeyDelegate(T item);
/// <summary>
/// The Key of this group.
/// </summary>
public string Key { get; private set; }
/// <summary>
/// Public constructor.
/// </summary>
/// <param name="key">The key for this group.</param>
public AlphaKeyGroup(string key)
{
Key = key;
}
public AlphaKeyGroup(IGrouping<string, T> grouping)
{
Key = grouping.Key;
this.AddRange(grouping);
}
/// <summary>
/// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping.
/// </summary>
/// <param name="slg">The </param>
/// <returns>Theitems source for a LongListSelector</returns>
private static List<AlphaKeyGroup<T>> CreateGroups(SortedLocaleGrouping slg)
{
List<AlphaKeyGroup<T>> list = new List<AlphaKeyGroup<T>>();
foreach (string key in slg.GroupDisplayNames)
{
if (key == "...")
{
list.Add(new AlphaKeyGroup<T>(GlobeGroupKey));
}
else
{
list.Add(new AlphaKeyGroup<T>(key));
}
}
return list;
}
/// <summary>
/// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping.
/// </summary>
/// <param name="items">The items to place in the groups.</param>
/// <param name="ci">The CultureInfo to group and sort by.</param>
/// <param name="getKey">A delegate to get the key from an item.</param>
/// <param name="sort">Will sort the data if true.</param>
/// <returns>An items source for a LongListSelector</returns>
public static List<AlphaKeyGroup<T>> CreateGroups(IEnumerable<T> items, CultureInfo ci, GetKeyDelegate getKey, bool sort)
{
SortedLocaleGrouping slg = new SortedLocaleGrouping(ci);
List<AlphaKeyGroup<T>> list = CreateGroups(slg);
foreach (T item in items)
{
int index = 0;
if (slg.SupportsPhonetics)
{
//check if your database has yomi string for item
//if it does not, then do you want to generate Yomi or ask the user for this item.
//index = slg.GetGroupIndex(getKey(Yomiof(item)));
}
else
{
index = slg.GetGroupIndex(getKey(item));
}
if (index >= 0 && index < list.Count)
{
list[index].Add(item);
}
}
if (sort)
{
foreach (AlphaKeyGroup<T> group in list)
{
group.Sort((c0, c1) => { return ci.CompareInfo.Compare(getKey(c0), getKey(c1)); });
}
}
return list;
}
}
The FilmatesInGroup.cs and FilmatesByName.cs is the same as PeopleInGroup.cs and PeopleByFirstName.cs in the PhoneToolKit example with the names adapted.
The longlistFilmates LongListSelector Object is inserted directly inside the PivotItem no.3 ( no Grid and no ScrollView )
Thanks in advance for any help!
Related
I have a paradigm which plays audio stimuli followed by images of the stimuli to be selected by the user. I need to replace the audio stimuli with video. Here is the original session code/implementation of the paradigm. At the end is one of my failed attempts at editing the session code that freezes trying to play. I could not fit all of the code, please let me know what else I should add of use.
Session:
using System;
using System.Linq;
using System.Media;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Text;
namespace Memory
{
/// <summary>
/// this handles the creation, tracking, and scoring of a single session
/// </summary>
class Session
{
#region class Vars/Properties
File save;
ItemsPool _all, _presented, _selected, _displayed;
initVars Vars = initVars.defaults;
sessTimer _timer;
System.Timers.Timer onset;
bool p_onset = false;
string _output = "Memdata." + DateTime.Now.ToString("Mdyy-HHmm") + ".txt";
int _sessCount = 0;
SoundPlayer player;
/// <summary>
/// a collection of the sum of the scores for this session
/// </summary>
List<int[]> ScoreSum;
/// <summary>
/// the Sum of time results
/// </summary>
int TimesSum = 0;
/// <summary>
/// the number of items to display
/// </summary>
int _itemCount;
/// <summary>
/// the number of items to display
/// </summary>
public int itemCount
{
get { return _itemCount; }
set { _itemCount = value; }
}
/// <summary>
/// the session count
/// </summary>
public int SessionCount { get { return _sessCount; } }
string _prefix = "";
/// <summary>
/// the prefix for the Rows
/// </summary>
public string RowPrefix
{
get { return _prefix; }
set { _prefix = value; }
}
/// <summary>
/// the image width for each item
/// </summary>
public int ImgWidth { get; set; }
/// <summary>
/// the max runs for this session
/// </summary>
public int maxRuns { get; set; }
/// <summary>
/// debug value
/// </summary>
public bool debug { get { return Vars.debug; } }
/// <summary>
/// the onset value
/// </summary>
public int onsetValue { get { return Vars.onset; } }
/// <summary>
/// view Images before Audio
/// </summary>
public bool ViewImages { get { return Vars.ViewImages; } }
/// <summary>
/// allow correction
/// </summary>
public bool AllowCorrection { get { return Vars.allowCorrection; } }
/// <summary>
/// play sounds one at a time
/// </summary>
public bool playOne { get { return Vars.playOne; } }
#endregion
#region constructors
/// <summary>
/// create a new session and load settings from an XML string or file
/// </summary>
/// <param name="xml">either a path or a string of XML</param>
/// <param name="SaveName">the name of the output file</param>
public Session(string xml, string output, bool makeUnique)
{
if (output != "")
{ _output = output; }
save = new File(_output);
if (makeUnique)
{ save.MakeUnique(); }
XDocument setupXML;
//check to see if there are any XML nodes ie. is this a string of XML, or a path
string fchar = xml.Substring(0, 1);
if (fchar == "<")
{ setupXML = XDocument.Parse(xml); }
else
{ setupXML = XDocument.Load(xml); }
LoadXML(setupXML);
//set some class vars based on the initial vars
//these are variables that may change during the session
_itemCount = Vars.Columns;
ScoreSum = new List<int[]>();
ImgWidth = Vars.width;
maxRuns = Vars.maxRuns;
_presented = new ItemsPool();
_selected = new ItemsPool();
_timer = new sessTimer();
_timer.Update += new EventHandler<StringEventArgs>(_timer_Update);
}
void LoadXML(XDocument setupXML)
{
// get the initial variables
var initVars = from feed in setupXML.Descendants("var")
select new
{
Name = feed.Attribute("Name").Value,
Value = feed.Value
};
foreach (var feed in initVars)
{ Vars.SetVar(feed.Name, feed.Value); }
// parse the image and audio filename
var ifiles = from feed in setupXML.Descendants("stim")
select new Item
{
Name = feed.Attribute("Name").Value,
audio = feed.Element("audio").Value,
image = feed.Element("image").Value
};
_all = new ItemsPool();
foreach (Item it in ifiles)
{
_all.add(Item.getItem(it.Name
, Vars.ImageDirectory + it.image
, Vars.AudioDirectory + it.audio
));
}
}
#endregion
#region public methods
/// <summary>
/// randomly generate an items pool for playback
/// </summary>
/// <returns></returns>
public ItemsPool RandPresentation()
{
_presented = new ItemsPool();
_presented = RandPool(_itemCount, _all);
if (Vars.Randomize)
{
_displayed = new ItemsPool();
_displayed = RandPool(_itemCount, _presented);
}
else
{ _displayed = _presented; }
return _displayed;
}
ItemsPool RandPool(int count, ItemsPool pool)
{
ItemsPool rp = new ItemsPool();
Item it = RandItem(pool);
//get new randoms until we have enough
do
{
//since only unique items may be added to an ItemPool,
//we don't need to check if the the pool contains the random item
it = RandItem(pool);
rp.add(it);
} while (rp.count < count);
return rp;
}
/// <summary>
/// clear all, and start a new session
/// </summary>
public void startNew()
{
if (_timer.Active)
{ stopTimer(); }
_sessCount++;
_selected = new ItemsPool();
}
/// <summary>
/// decrement the session count
/// </summary>
public void decSessCount()
{
if (_sessCount > 0)
{ _sessCount--; }
}
/// <summary>
/// log the results to the save file
/// </summary>
public void LogResults()
{
if (_sessCount > 0)
{ logResults(); }
}
/// <summary>
/// add an item to the selected pool.
/// </summary>
/// <param name="it"></param>
public void Selected(Item it)
{
_selected.add(it);
if (_selected.count == _itemCount)
{
stopTimer();
LogResults();
}
}
private void stopTimer()
{
_timer.stop();
timerStopped(this, new EventArgs());
}
/// <summary>
/// remove an item from the selected pool
/// </summary>
/// <param name="it"></param>
public void remove(Item it)
{
if (_selected.Contains(it))
{
_selected.remove(it);
}
}
public void logSummary()
{
string[] lineSC = new string[_itemCount + 3];
string lineF = "\t\t{0}\t{1}";
string sumHdr1 = "\t\tPart\tN";
if (RowPrefix.Length > 7)
{
lineF = "\t{0}\t{1}";
sumHdr1 = "\tPart\t\tN";
}
lineSC[0] = String.Format(lineF, RowPrefix, _sessCount.ToString());
int ItemSum = 0;
//go through each column, get the sum
for (int i = 0; i < _itemCount; i++)
{
int cSum = 0;
//go through the list and get the score results for this column
foreach (int[] iarr in ScoreSum)
{
cSum += iarr[i];
}
ItemSum += cSum;
lineSC[i + 1] = cSum.ToString();
}
//Mean Time
double MTime = ((double)TimesSum / (double)_sessCount);
MTime = Math.Round(MTime, 3);
lineSC[_itemCount + 1] = MTime.ToString();
//Mean Sum
//double MSum = ((double)ItemSum / (double)_itemCount);
//MSum = Math.Round(MSum, 3);
//lineSC[_itemCount + 2] = MSum.ToString();
//Sum
lineSC[_itemCount + 2] = ItemSum.ToString();
//create the header
string[] sumHdr = new string[_itemCount + 2];
sumHdr[0] = sumHdr1;
for (int i = 0; i < _itemCount; i++)
{
sumHdr[i + 1] = "Itm" + (i + 1).ToString();
}
sumHdr[_itemCount + 1] = "M_Time\tSum";
//put to file
save.Append(dashBreak());
save.Append(sumHdr);
save.Append(lineSC);
save.Append(dashBreak());
}
string dashBreak()
{
StringBuilder sb = new StringBuilder("|--------");
for (int i = 0; i < _itemCount + 3; i++)
{
sb.Append("--------");
if (i == _itemCount + 2)
{
sb.Append("-----------|");
}
}
return sb.ToString();
}
#endregion
#region private methods
/// <summary>
/// save the session's results to a text file
/// </summary>
void logResults()
{
//there should be a scoring method here and perhaps an option to
//output scores instead of text options, but Susan did not want that.
//added scoring 5/8/09
int iCount = _presented.count;
string[] score = new string[iCount + 2];
int[] scs = new int[iCount];
for (int i = 0; i < iCount; i++)
{
Item pre = _presented.getItem(i);
Item sel = _selected.getItem(i);
int sc = 1;
//if (Item.Compare(pre,sel))
//{ sc = 1; }
if (pre.Name == sel.Name )
{ sc = 0; }
score[i + 1] = sc.ToString();
scs[i] = sc;
}
//log for the summary
ScoreSum.Add(scs);
TimesSum += _timer.Time;
//create array for log file
score[0] = String.Format("{0}\t{1}\t{2}", RowPrefix, _sessCount.ToString(), "errs");
score[iCount + 1] = _timer.Time.ToString();
//add the presented line
save.Append(MakeRow(_presented, "pres"));
//add the selected line
save.Append(MakeRow(_selected, "sel"));
//add the score line
save.Append(score);
//put an extra line in there
save.Append("");
}
string[] MakeRow(ItemsPool ip, string prefix)
{
string[] row = new string[ip.count + 1]; // 2];
row[0] = String.Format("{0}\t{1}\t{2}",RowPrefix, _sessCount.ToString(), prefix);
if (ip.count > 0)
{
for (int i = 0; i < ip.count; i++)
{
Item it = ip.getItem(i);
row[i + 1] = it.Name;
}
}
//row[ip.count + 1] = _timer.Time.ToString();
return row;
}
Item RandItem(ItemsPool pool)
{
//setup a new random object
Random r = new Random();
/* the random generator has a fear of the last option,
* so I'm giving it two chances to grab the last item...
* this may need adjustment.
*/
int _play = r.Next(pool.count + 1);
if (_play >= pool.count)
{ _play -= 1; }
Item ri = pool.getItem(_play);
return ri;
}
#endregion
#region audio player methods
void playItem(Item it)
{
player = new SoundPlayer();
player.LoadCompleted += new System.ComponentModel.AsyncCompletedEventHandler(player_LoadCompleted);
player.SoundLocation = it.audio;
player.Load();
}
void player_LoadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (p_onset)
{ player.Play(); }
else
{
player.PlaySync();
if (!Vars.playOne)
{ PlayNext(); }
}
}
int playQueue = 0;
public void playLast()
{
int p = playQueue;
if (p > 0)
{ p--; }
playItem(_presented.getItem(p));
}
public void PlayNext()
{
if (playQueue < _presented.count)
{
Item it = _presented.getItem(playQueue);
playQueue++;
playItem(it);
}
else
{
playQueue = 0;
_timer.start();
if (p_onset)
{
onset.Stop();
onset.Enabled = false;
onsetPlayFinished(this, new EventArgs());
}
}
}
public void playOnset()
{
p_onset = true;
onset = new System.Timers.Timer(Vars.onset);
onset.Elapsed += new System.Timers.ElapsedEventHandler(onset_Elapsed);
onset.Enabled = true;
if (!Vars.playOne)
{
PlayNext();
onset.Start();
}
}
void onset_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!Vars.playOne)
{ PlayNext(); }
}
#endregion
#region events & handlers
public event EventHandler onsetPlayFinished;
public event EventHandler<StringEventArgs> TimerUpdate;
public event EventHandler timerStopped;
void _timer_Update(object sender, StringEventArgs e)
{ TimerUpdate(sender, e); }
#endregion
}
}
My Code:
using System;
using System.Linq;
using System.Media;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Text;
using WMPLib;
using AxWMPLib;
namespace Memory
{
/// <summary>
/// this handles the creation, tracking, and scoring of a single session
/// </summary>
class Session
{
#region class Vars/Properties
File save;
ItemsPool _all, _presented, _selected, _displayed;
initVars Vars = initVars.defaults;
sessTimer _timer;
System.Timers.Timer onset;
bool p_onset = false;
string _output = "Memdata." + DateTime.Now.ToString("Mdyy-HHmm") + ".txt";
int _sessCount = 0;
AxWindowsMediaPlayer axWindowsMediaPlayer1;
/// <summary>
/// a collection of the sum of the scores for this session
/// </summary>
List<int[]> ScoreSum;
/// <summary>
/// the Sum of time results
/// </summary>
int TimesSum = 0;
/// <summary>
/// the number of items to display
/// </summary>
int _itemCount;
/// <summary>
/// the number of items to display
/// </summary>
public int itemCount
{
get { return _itemCount; }
set { _itemCount = value; }
}
/// <summary>
/// the session count
/// </summary>
public int SessionCount { get { return _sessCount; } }
string _prefix = "";
/// <summary>
/// the prefix for the Rows
/// </summary>
public string RowPrefix
{
get { return _prefix; }
set { _prefix = value; }
}
/// <summary>
/// the image width for each item
/// </summary>
public int ImgWidth { get; set; }
///<summary>
///video width for each item
/// </summary>
public int VidWidth { get; set; }
/// <summary>
/// the max runs for this session
/// </summary>
public int maxRuns { get; set; }
/// <summary>
/// debug value
/// </summary>
public bool debug { get { return Vars.debug; } }
/// <summary>
/// the onset value
/// </summary>
public int onsetValue { get { return Vars.onset; } }
/// <summary>
/// view Images before Audio
/// </summary>
public bool ViewImages { get { return Vars.ViewImages; } }
/// <summary>
/// allow correction
/// </summary>
public bool AllowCorrection { get { return Vars.allowCorrection; } }
/// <summary>
/// play sounds one at a time
/// </summary>
public bool playOne { get { return Vars.playOne; } }
#endregion
#region constructors
/// <summary>
/// create a new session and load settings from an XML string or file
/// </summary>
/// <param name="xml">either a path or a string of XML</param>
/// <param name="SaveName">the name of the output file</param>
public Session(string xml, string output, bool makeUnique)
{
if (output != "")
{ _output = output; }
save = new File(_output);
if (makeUnique)
{ save.MakeUnique(); }
XDocument setupXML;
//check to see if there are any XML nodes ie. is this a string of XML, or a path
string fchar = xml.Substring(0, 1);
if (fchar == "<")
{ setupXML = XDocument.Parse(xml); }
else
{ setupXML = XDocument.Load(xml); }
LoadXML(setupXML);
//set some class vars based on the initial vars
//these are variables that may change during the session
_itemCount = Vars.Columns;
ScoreSum = new List<int[]>();
ImgWidth = Vars.width;
maxRuns = Vars.maxRuns;
_presented = new ItemsPool();
_selected = new ItemsPool();
_timer = new sessTimer();
_timer.Update += new EventHandler<StringEventArgs>(_timer_Update);
}
void LoadXML(XDocument setupXML)
{
// get the initial variables
var initVars = from feed in setupXML.Descendants("var")
select new
{
Name = feed.Attribute("Name").Value,
Value = feed.Value
};
foreach (var feed in initVars)
{ Vars.SetVar(feed.Name, feed.Value); }
// parse the image and audio filename
var ifiles = from feed in setupXML.Descendants("stim")
select new Item
{
Name = feed.Attribute("Name").Value,
video = feed.Element("video").Value,
image = feed.Element("image").Value
};
_all = new ItemsPool();
foreach (Item it in ifiles)
{
_all.add(Item.getItem(it.Name
, Vars.ImageDirectory + it.image
, Vars.VideoDirectory + it.video
));
}
}
#endregion
#region public methods
/// <summary>
/// randomly generate an items pool for playback
/// </summary>
/// <returns></returns>
public ItemsPool RandPresentation()
{
_presented = new ItemsPool();
_presented = RandPool(_itemCount, _all);
if (Vars.Randomize)
{
_displayed = new ItemsPool();
_displayed = RandPool(_itemCount, _presented);
}
else
{ _displayed = _presented; }
return _displayed;
}
ItemsPool RandPool(int count, ItemsPool pool)
{
ItemsPool rp = new ItemsPool();
Item it = RandItem(pool);
//get new randoms until we have enough
do
{
//since only unique items may be added to an ItemPool,
//we don't need to check if the the pool contains the random item
it = RandItem(pool);
rp.add(it);
} while (rp.count < count);
return rp;
}
/// <summary>
/// clear all, and start a new session
/// </summary>
public void startNew()
{
if (_timer.Active)
{ stopTimer(); }
_sessCount++;
_selected = new ItemsPool();
}
/// <summary>
/// decrement the session count
/// </summary>
public void decSessCount()
{
if (_sessCount > 0)
{ _sessCount--; }
}
/// <summary>
/// log the results to the save file
/// </summary>
public void LogResults()
{
if (_sessCount > 0)
{ logResults(); }
}
/// <summary>
/// add an item to the selected pool.
/// </summary>
/// <param name="it"></param>
public void Selected(Item it)
{
_selected.add(it);
if (_selected.count == _itemCount)
{
stopTimer();
LogResults();
}
}
private void stopTimer()
{
_timer.stop();
timerStopped(this, new EventArgs());
}
/// <summary>
/// remove an item from the selected pool
/// </summary>
/// <param name="it"></param>
public void remove(Item it)
{
if (_selected.Contains(it))
{
_selected.remove(it);
}
}
public void logSummary()
{
string[] lineSC = new string[_itemCount + 3];
string lineF = "\t\t{0}\t{1}";
string sumHdr1 = "\t\tPart\tN";
if (RowPrefix.Length > 7)
{
lineF = "\t{0}\t{1}";
sumHdr1 = "\tPart\t\tN";
}
lineSC[0] = String.Format(lineF, RowPrefix, _sessCount.ToString());
int ItemSum = 0;
//go through each column, get the sum
for (int i = 0; i < _itemCount; i++)
{
int cSum = 0;
//go through the list and get the score results for this column
foreach (int[] iarr in ScoreSum)
{
cSum += iarr[i];
}
ItemSum += cSum;
lineSC[i + 1] = cSum.ToString();
}
//Mean Time
//Same as original code
//Mean Sum
//same as original code
//Sum
lineSC[_itemCount + 2] = ItemSum.ToString();
//create the header
string[] sumHdr = new string[_itemCount + 2];
sumHdr[0] = sumHdr1;
for (int i = 0; i < _itemCount; i++)
{
sumHdr[i + 1] = "Itm" + (i + 1).ToString();
}
sumHdr[_itemCount + 1] = "M_Time\tSum";
//put to file
save.Append(dashBreak());
save.Append(sumHdr);
save.Append(lineSC);
save.Append(dashBreak());
}
string dashBreak()
{
StringBuilder sb = new StringBuilder("|--------");
for (int i = 0; i < _itemCount + 3; i++)
{
sb.Append("--------");
if (i == _itemCount + 2)
{
sb.Append("-----------|");
}
}
return sb.ToString();
}
#endregion
#region private methods
/// <summary>
/// save the session's results to a text file
/// </summary>
void logResults()
{
//there should be a scoring method here and perhaps an option to
//output scores instead of text options, but Susan did not want that.
//added scoring 5/8/09
int iCount = _presented.count;
string[] score = new string[iCount + 2];
int[] scs = new int[iCount];
for (int i = 0; i < iCount; i++)
{
Item pre = _presented.getItem(i);
Item sel = _selected.getItem(i);
int sc = 1;
//if (Item.Compare(pre,sel))
//{ sc = 1; }
if (pre.Name == sel.Name )
{ sc = 0; }
score[i + 1] = sc.ToString();
scs[i] = sc;
}
//log for the summary
ScoreSum.Add(scs);
TimesSum += _timer.Time;
//create array for log file
score[0] = String.Format("{0}\t{1}\t{2}", RowPrefix, _sessCount.ToString(), "errs");
score[iCount + 1] = _timer.Time.ToString();
//add the presented line
save.Append(MakeRow(_presented, "pres"));
//add the selected line
save.Append(MakeRow(_selected, "sel"));
//add the score line
save.Append(score);
//put an extra line in there
save.Append("");
}
string[] MakeRow(ItemsPool ip, string prefix)
{
string[] row = new string[ip.count + 1]; // 2];
row[0] = String.Format("{0}\t{1}\t{2}",RowPrefix, _sessCount.ToString(), prefix);
if (ip.count > 0)
{
for (int i = 0; i < ip.count; i++)
{
Item it = ip.getItem(i);
row[i + 1] = it.Name;
}
}
//row[ip.count + 1] = _timer.Time.ToString();
return row;
}
Item RandItem(ItemsPool pool)
{
//setup a new random object
Random r = new Random();
/* the random generator has a fear of the last option,
* so I'm giving it two chances to grab the last item...
* this may need adjustment.
*/
int _play = r.Next(pool.count + 1);
if (_play >= pool.count)
{ _play -= 1; }
Item ri = pool.getItem(_play);
return ri;
}
#endregion
#region video player methods
void playItem(Item it)
{
axWindowsMediaPlayer1 = new AxWindowsMediaPlayer();
axWindowsMediaPlayer1.PlayStateChange += new PlayStateChangeHandler(axWindowsMediaPlayer1_PlayStateChange);
this.axWindowsMediaPlayer1.URL ="it.video";
axWindowsMediaPlayer1.Ctlcontrols.play();
}
void axWindowsMediaPlayer1_LoadCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (p_onset)
{ axWindowsMediaPlayer1.Ctlcontrols.play(); }
else
{
axWindowsMediaPlayer1.Ctlcontrols.play();
if (!Vars.playOne)
{ PlayNext(); }
}
}
int playQueue = 0;
new EventArgs());
}
}
}
...end of code block same as original
I have a problem:
public class PaginationSet
{
public int TotalItemCount { get; set; }
public int Page { get; set; }
public int Amount { get; set; }
public string Sort { get; set; }
public string Order { get; set; }
/// <summary>
/// This is used to store all the above information in, while still maintaining the automated index count from the internal for loop link builder.
///
/// Don't forget to pass the index into this!
/// </summary>
public Func<int, object> PaginationLinkData
{
get
{
return index => new
{
page = index, // This is the internal pointer part that is used currently by Bootstrap pagination function
amount = this.Amount,
sort = this.Sort,
order = this.Order
};
}
}
}
this.Sort and this.Order are sometimes null. If they are, I would like to not place them inside the returning Func<int,object>... How do i go about doing this?
It might look something like this:
public Func<int, object> PaginationLinkData
{
get
{
Func<int,object> something = index => new
{
page = index, // This is the internal pointer part that is used currently by Bootstrap pagination function
amount = this.Amount
};
if( this.Sort != null )
{
something.sort = this.Sort,
something.order= this.Order
}
return something;
}
}
}
Try using expando object...
public Func<int, object> PaginationLinkData
{
get
{
return index =>
{
dynamic obj = new ExpandoObject();
obj.page = index;
obj.amount = this.Amount;
if (this.Sort != null)
{
obj.sort = this.Sort;
}
if (this.Order != null)
{
obj.order = this.Order;
}
return obj;
};
}
}
Can't you just do something like this?
public Func<int, object> PaginationLinkData
{
get
{
if( this.Sort != null )
{
return index => new
{
page = index, // This is the internal pointer part that is used currently by Bootstrap pagination function
amount = this.Amount,
sort = this.Sort,
order = this.Order
};
}
else
{
return index => new
{
page = index, // This is the internal pointer part that is used currently by Bootstrap pagination function
amount = this.Amount,
};
}
}
}
I am guessing you are serializing to JSon somewhere. If so and you can use dynamic why not:
/// <summary>
/// This is used to store all the above information in, while still maintaining the automated index count from the internal for loop link builder.
///
/// Don't forget to pass the index into this!
/// </summary>
public Func<int, object> PaginationLinkData
{
get
{
dynamic res = new ExpandoObject();
res.amount = Amount;
if (Sort != null) res.sort = Sort;
if (Order != null) res.order = Order;
return index =>
{
res.page = index;
return res;
};
}
}
namespace Winning.FrameWork.PageMenuSetting
{
public static class PreviewMenuHelper
{
/// <summary>
/// 预览数据返回类型
/// </summary>
public class TagPageInfo
{
public string TabPageName { get; set; }
public List<MenuGroupInfo> ListMenuGroups { get; set; }
}
/// <summary>
/// menugroup 返回类型
/// </summary>
public class MenuGroupInfo
{
public string GroupId{ get; set; }
public string GroupName{ get; set; }
public List<MenuItemInfo> MenuItems{ get; set; }
}
/// <summary>
/// menuitem 返回类型
/// </summary>
public class MenuItemInfo
{
public string CommandId { get; set; }
public string AliasName { get; set; }
public string ICON { get; set; }
public int ShowMode { get; set; }
public int ShowIndex { get; set; }
}
/// <summary>
/// 获得所有的指定pageid的menu
/// </summary>
public static List<TagPageInfo> GetPageMenuInfo(string pageid)
{
List<TagPageInfo> listPage = new List<TagPageInfo>();
TagPageInfo tagPageInfo = new TagPageInfo();
listPage.Add(tagPageInfo);
listPage[0].TabPageName = pageid.Trim();
MenuGroupInfo menuGroupInfo = new MenuGroupInfo();
MenuItemInfo menuItemInfo = new MenuItemInfo();
int groupid = 1 ;
var MenuItemsInfos = DataHelper.DataObj.QueryTable<PUB_MENU_ITEMINFO>(SystemType.H0, p => p.PAGEID.Trim() == pageid.Trim());
listPage[0].ListMenuGroups = new List<MenuGroupInfo>();
foreach (PUB_MENU_ITEMINFO item in MenuItemsInfos)
{
if (listPage[0].ListMenuGroups.Count<=0|| listPage[0].ListMenuGroups.FirstOrDefault(p => p.GroupName == item.MEMO) == null)
{
menuGroupInfo.GroupId = groupid.ToString();
menuGroupInfo.GroupName = item.MEMO;
menuItemInfo.CommandId = item.COMMANDID;
menuItemInfo.AliasName = item.MENUITEMNAME;
menuItemInfo.ICON = item.ICON;
menuItemInfo.ShowMode = 0;
menuItemInfo.ShowIndex = 1;
menuGroupInfo.MenuItems = new List<MenuItemInfo>();
menuGroupInfo.MenuItems.Add(menuItemInfo);
listPage[0].ListMenuGroups = new List<MenuGroupInfo>();
listPage[0].ListMenuGroups.Add(menuGroupInfo);
groupid++;
}
else
{
//var existgroup = listPage[0].ListMenuGroups.FirstOrDefault(t => t.GroupName == item.MEMO) as MenuGroupInfo;
menuItemInfo.AliasName=item.MENUITEMNAME;
menuItemInfo.CommandId=item.COMMANDID;
menuItemInfo.ShowMode = 0;
menuItemInfo.ShowIndex = 1;
//this is where the problem is. all items inside the list<menuiteminfo> become the same as the last menuiteminfo i insert into.
((listPage[0].ListMenuGroups.FirstOrDefault(t => t.GroupName == item.MEMO) as MenuGroupInfo).MenuItems as List<MenuItemInfo>).Add(menuItemInfo);
}
}
return listPage;
}
}
}
Could not insert new menuiteminfo into the one exist menugroupinfo.
All the menuiteminfo become the last item I insert into, don't know why! Please mainly check the several last line to point where I go wrong!
MenuGroupInfo menuGroupInfo = new MenuGroupInfo();
MenuItemInfo menuItemInfo = new MenuItemInfo();
problem solved, i defined a globle viriable. so all the new MenuItemInfo are add into the single MenuGroupInfo.
I have following ObservableCollection in my class, I am binding data to my listbox using that Collection in my Windows phone 7 application
public ObservableCollection<CustomClass> myList = new ObservableCollection<CustomClass>();
My Custom Class
public class CustomClass
{
public string Id { get; set; }
public string Name { get; set; }
public string EventName { get; set; }
public string EventDate get
{
return EventDate;
}
set
{
if (value != null)
{
DateTime eventDate = DateTime.Parse(value);
int today = DateTime.Now.Day;
if (eventDate.Day <= today + 1 & eventDate.Day >= today - 2)
{
if (eventDate.Day == today)
EventDate = "Today";
else if (eventDate.Day == (today + 1))
EventDate = "Tomorrow";
else if (eventDate.Day == (today - 1))
EventDate = "Yesterday";
else if (eventDate.Day >= (today - 2))
EventDate = "Just Passed";
}
else
{
EventDate = value;
}
}
}
}
Now i want to sort myList according to the data in the EventDate
The Data in the EventDate will be one of the following in all the cases
Just Passed
Yesterday
Tomorrow
Today
Date //Format "MMM/dd"
Custom Collection must be sorted according to the above order only
i am getting data from different sources so sorting is not possible at the time of binding data into the collection
Is it possible??
Since your CustomClass doesn't implement INotifyPropertyChange, I'm assuming you'll only have to sort at insert (when adding to the collection). So IMHO, the easiest thing to do (similiar to Randolf Rincón-Fadul's solution) is to subclass, then override the Add method.
public class ComparingObservableCollection<T> : ObservableCollection<T>
where T : IComparable<T>
{
protected override void InsertItem(int index, T item)
{
int i = 0;
bool found = false;
for (i = 0; i < Items.Count; i++)
{
if (item.CompareTo(Items[i]) < 0) {
found = true;
break;
}
}
if (!found) i = Count;
base.InsertItem(i, item);
}
}
Then all you have to do is implement IComparable<CustomClass> on CustomClass like this:
public class CustomClass : IComparable<CustomClass>
{
public string Id { get; set; }
public string Name { get; set; }
public string EventName { get; set; }
public string EventDate { get
{
return EventDate;
}
set
{
if (value != null)
{
DateTime eventDate = DateTime.Parse(value);
int today = DateTime.Now.Day;
if (eventDate.Day <= today + 1 & eventDate.Day >= today - 2)
{
if (eventDate.Day == today)
EventDate = "Today";
else if (eventDate.Day == (today + 1))
EventDate = "Tomorrow";
else if (eventDate.Day == (today - 1))
EventDate = "Yesterday";
else if (eventDate.Day >= (today - 2))
EventDate = "Just Passed";
}
else
{
EventDate = value;
}
}
}
private int Order { get {
switch(EventDate) {
case "Just Passed": return 1;
case "Yesterday": return 2;
case "Tomorrow": return 3;
case "Today": return 4;
default: return 5;
}
}
}
public int CompareTo(CustomClass other) {
return this.Order.CompareTo(other.Order);
}
}
Taken a look here??
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/5909dbcc-9a9f-4260-bc36-de4aa9bbd383/
A few decent answers towards the bottom.
You can always subclass:
/// <summary>
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed and allows sorting.
/// </summary>
/// <typeparam name="T">The type of elements in the collection.</typeparam>
public class SortableObservableCollection<T> : ObservableCollection<T>
{
/// <summary>
/// Sorts the items of the collection in ascending order according to a key.
/// </summary>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
/// <param name="keySelector">A function to extract a key from an item.</param>
public void Sort<TKey>(Func<T, TKey> keySelector)
{
InternalSort(Items.OrderBy(keySelector));
}
/// <summary>
/// Sorts the items of the collection in ascending order according to a key.
/// </summary>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
/// <param name="keySelector">A function to extract a key from an item.</param>
/// <param name="comparer">An <see cref="IComparer{T}"/> to compare keys.</param>
public void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer)
{
InternalSort(Items.OrderBy(keySelector, comparer));
}
/// <summary>
/// Moves the items of the collection so that their orders are the same as those of the items provided.
/// </summary>
/// <param name="sortedItems">An <see cref="IEnumerable{T}"/> to provide item orders.</param>
private void InternalSort(IEnumerable<T> sortedItems)
{
var sortedItemsList = sortedItems.ToList();
foreach (var item in sortedItemsList)
{
Move(IndexOf(item), sortedItemsList.IndexOf(item));
}
}
}
And then sort using a lambda expression
((SortableObservableCollection<CustomClass>)MyList).Sort(s => s.EventDate);
I have own collection DataContracts:
[DataContract]
public class DzieckoAndOpiekun
{
public DzieckoAndOpiekun() { }
public DzieckoAndOpiekun(string dzImie, string dzNazwisko, string opImie, string opNazwisko)
{
this.DzieckoImie = dzImie;
this.DzieckoImie = dzNazwisko;
this.OpiekunImie = opImie;
this.OpiekunNazwisko = opNazwisko;
}
/// <summary>
/// Field for Dziecko's Surname
/// </summary>
private string dzieckoNazwisko;
/// <summary>
/// Field for Dziecko's Name
/// </summary>
private string dzieckoImie;
/// <summary>
/// Field for Opiekun's Surname
/// </summary>
private string opiekunNazwisko;
/// <summary>
/// Field for Opiekun's Name
/// </summary>
private string opiekunImie;
/// <summary>
/// Gets or sets the dziecko nazwisko.
/// </summary>
/// <value>The dziecko nazwisko.</value>
[DataMember]
public virtual string DzieckoNazwisko
{
get { return this.dzieckoNazwisko; }
set { this.dzieckoNazwisko = value; }
}
/// <summary>
/// Gets or sets the dziecko imie.
/// </summary>
/// <value>The dziecko imie.</value>
[DataMember]
public virtual string DzieckoImie
{
get { return this.dzieckoImie; }
set { this.dzieckoImie = value; }
}
/// <summary>
/// Gets or sets the opiekun nazwisko.
/// </summary>
/// <value>The opiekun nazwisko.</value>
[DataMember]
public virtual string OpiekunNazwisko
{
get { return this.opiekunNazwisko; }
set { this.opiekunNazwisko = value; }
}
/// <summary>
/// Gets or sets the opiekun imie.
/// </summary>
/// <value>The opiekun imie.</value>
[DataMember]
public virtual string OpiekunImie
{
get { return this.opiekunImie; }
set { this.opiekunImie = value; }
}
}
[DataContract]
public class DzieckoAndOpiekunCollection : IEnumerable<DzieckoAndOpiekun>, IList<DzieckoAndOpiekun>
{
[DataMember]
List<DzieckoAndOpiekun> collection = new List<DzieckoAndOpiekun>();
[DataMember]
public List<DzieckoAndOpiekun> Collection
{
get { return collection; }
set { collection = value; }
}
public IEnumerator<DzieckoAndOpiekun> GetEnumerator()
{
return collection.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new System.NotImplementedException();
}
public int IndexOf(DzieckoAndOpiekun item)
{
return collection.IndexOf(item);
}
public void Insert(int index, DzieckoAndOpiekun item)
{
collection.Insert(index, item);
}
public void RemoveAt(int index)
{
collection.RemoveAt(index);
}
public DzieckoAndOpiekun this[int index]
{
get
{
return collection[index];
}
set
{
collection[index] = value;
}
}
public void Add(DzieckoAndOpiekun item)
{
this.collection.Add(item);
}
public void AddRange(IList<DzieckoAndOpiekun> collection)
{
this.collection.AddRange(collection);
}
public void Clear()
{
collection.Clear();
}
public bool Contains(DzieckoAndOpiekun item)
{
return collection.Contains(item);
}
public void CopyTo(DzieckoAndOpiekun[] array, int arrayIndex)
{
this.collection.CopyTo(array, arrayIndex);
}
public int Count
{
get { return this.collection.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(DzieckoAndOpiekun item)
{
return this.collection.Remove(item);
}
}
And use it in my ServiceContract implementation:
public DzieckoAndOpiekunCollection GetChildAndOpiekunByFirstnameLastname(string firstname, string lastname)
{
DataTransfer.ChargeInSchoolEntities db = new DataTransfer.ChargeInSchoolEntities();
DzieckoAndOpiekunCollection result = new DzieckoAndOpiekunCollection();
if (firstname == null && lastname != null)
{
IQueryable<DzieckoAndOpiekun> resultV = from p in db.Dziecko
where lastname == p.Nazwisko
select new DzieckoAndOpiekun(
p.Imie,
p.Nazwisko,
p.Opiekun.Imie,
p.Opiekun.Nazwisko);
List<DzieckoAndOpiekun> l = resultV.ToList();
result.AddRange(l);
}
if (firstname != null && lastname != null)
{
IQueryable<DzieckoAndOpiekun> resultV = from p in db.Dziecko
where firstname == p.Imie && lastname == p.Nazwisko
select new DzieckoAndOpiekun(
p.Imie,
p.Nazwisko,
p.Opiekun.Imie,
p.Opiekun.Nazwisko);
List<DzieckoAndOpiekun> l = resultV.ToList();
result.AddRange(l);
}
if (firstname != null && lastname == null)
{
IQueryable<DzieckoAndOpiekun> resultV = from p in db.Dziecko
where firstname == p.Imie
select new DzieckoAndOpiekun(
p.Imie,
p.Nazwisko,
p.Opiekun.Imie,
p.Opiekun.Nazwisko);
List<DzieckoAndOpiekun> l = resultV.ToList();
result.AddRange(l);
}
return result;
}
Do I something wrong in creating own data contract and sending it ? I ask cause I have errors when consuming method :/ :
An exception occurred during the operation, making the result invalid.
Check InnerException for exception
details.
at
System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary()
at
SecretaryAppNav.ClientService.GetChildAndOpiekunByFirstnameLastnameCompletedEventArgs.get_Result() at
SecretaryAppNav.Views.FindChild.Client_GetChildAndOpiekunByFirstnameLastnameCompleted(Object
sender,
GetChildAndOpiekunByFirstnameLastnameCompletedEventArgs
e)
at SecretaryAppNav.ClientService.Service1Client.OnGetChildAndOpiekunByFirstnameLastnameCompleted(Object
state)
I can't guarantee that this would work, but you are sending the collection twice:
[DataContract]
public class DzieckoAndOpiekunCollection :
IEnumerable<DzieckoAndOpiekun>, IList<DzieckoAndOpiekun>
{
[DataMember]
List<DzieckoAndOpiekun> collection = new List<DzieckoAndOpiekun>();
[DataMember]
public List<DzieckoAndOpiekun> Collection
{
get { return collection; }
set { collection = value; }
}
...
You should probably only place the DataMember attribute on the field or the property, but not both, since they are exposing the same value.
I solve the problem with CollectionDataContract attribute ;)