Part 14: Binding to Real Data at Runtime

Sign in to queue

The Discussion

  • User profile image
    QuocTruong

    Awesome. Now I can load data from XAML/XML file at run time Smiley.

  • User profile image
    Richard Freytag

    I decided to forego a lot of the typing and wrote a procedure that built SoundGroups instead:

    public bool LoadData()
    {
    // load data here.
    this.Animals = CreateSoundGroup("Assets/Audio/Animals");
    this.Cartoons = CreateSoundGroup("Assets/Audio/Cartoons");
    this.Taunts = CreateSoundGroup("Assets/Audio/Taunts");
    this.Warnings = CreateSoundGroup("Assets/Audio/Warnings");

    return IsDataLoaded = true;
    }

    private SoundGroup CreateSoundGroup(string pSoundDirectory)
    {
    List<String> soundFiles = new List<String>(Directory.GetFiles(pSoundDirectory));
    SoundGroup soundGroup = new SoundGroup();

    foreach (String soundPath in soundFiles)
    {
    SoundData sound = new SoundData();

    sound.FilePath = soundPath;
    sound.Title = soundPath.Split('\\').Last().Split('.').First();

    soundGroup.Items.Add(sound);
    soundGroup.Title = soundPath.Split('\\').First().Split('/').Last();
    }

    return soundGroup;
    }

  • User profile image
    Clint

    @Richard Freytag: cool, issue becomes mapping name to the sound.  Lots of ways to solve the problem

  • User profile image
    Anh Duong

    Thank you very much for the series.

    In this Part 14, I don't really understand why Bob had to add the line " viewModel.LoadData(); " into the " If statement" near the end to make the Group Titles appear.

    I am almost ready to rebuild this app myself and this is the only part I am having problem with. Please help me.

  • User profile image
    BobTabor

    @Anh Duong: I believe this was a timing issue, if I recall.  The headers and the data bound to the tiles loads at different moments / events in the lifecycle.  I had to explicitly call the Load() to get the titles to load at the right time, otherwise, they would no appear.  Try that, experiment, and see what I mean.  I'm not sure how to explain it beyond that.  Hope that helps! 

  • User profile image
    Anh Duong

    @BobTabor: Thank you for your response. I understand your explanation; however, the original code of the Template doesn't contain that line, and it does make the Group Titles appear. That is what I am struggling with.

  • User profile image
    Anh Duong

    Oh I have just looked at the code again and realized that in the template they hard coded the Group Titles into the MainPage.Xaml file!
    I think I got it, on my way recreating this cute app!

  • User profile image
    Danny

    can someone explain to me what does the following means?
    "re-create this app using a different data access technique, such as expanding the SampleData.xaml file with real data, then loading that data at RUN TIME."

    Do i need to load data from xaml file and create objects according to the data in the xaml file? don't i need a corresponding dtd file that holds the structure of the xaml file in order to use it

  • User profile image
    BobTabor

    @Danny: Yes, so if you look at the default template for a Windows Phone 8 project, it pushes you to a certain style of data access.  There's a "design time" approach and a "run time" approach.  Again, by default, the "design time" utilizes a file filled with data SO THAT the designer in Visual Studio can display fake data.  Fake data is helpful so that you can see the aesthetic design of the form you're building.  However, at "run time" the REAL data is provided by a set of hard coded instances of collections of classes.

    My challenge (think: homework ... something to help you flex your programming muscle) was this ... instead of using two different techniques for data access -- one for design time and one for run time -- change the run time approach to utilize the file of data we already are using for design time.

    Does that clarification make more sense?

  • User profile image
    Danny

    @BobTabor: ok thank you for the clarification!
    So as I wrote before do I need to find a technique to load data from xaml or do I need to find a way to bind the data in the load data method?

    a couple more questions, if I may:
    1. what is the difference between Binding and StaticResources? does the second one refers to styles and first one for data\none-hard-coded-data?

    2. what does the Path and Source attributes in the Binding statement mean? I saw the use of the those in Localization Lesson but I still can't understand what is the responsibility of each of them

  • User profile image
    Thierry

    Hi,

    I've just discovered the tutorials! Great so far!! Here is a bit of code I've created instead of creating an entry for each sound! Works a charm! I've haven't tried it on my phone just yet, but from reading the code above, there's no mapping issues, at least not on the emulator!

    I've just spotted very similar code has been posted, but no arm in posting a slightly different variance of it I guess!

    public void LoadData()
    {
    Animals = CreateItemsForGroup("Animals");
    Cartoons = CreateItemsForGroup("Cartoons");
    Taunts = CreateItemsForGroup("Taunts");
    Warnings = CreateItemsForGroup("Warnings");
    IsDataLoaded = true;
    }

    private SoundGroupViewModel CreateItemsForGroup(string soundType)
    {
    SoundGroupViewModel soundGroupViewModel = new SoundGroupViewModel();
    soundGroupViewModel.Title = soundType.ToLower();

    string path = @".\Assets\Audio\" + soundType;

    foreach (string sound in Directory.GetFiles(path))
    {
    string title = Path.GetFileNameWithoutExtension(sound);
    string filePath = sound;
    soundGroupViewModel.Items.Add(new SoundDataModel() { Title = title, FilePath = filePath });
    }
    return soundGroupViewModel;
    }

  • User profile image
    Clint
    @Thierry: the reason why I coded it like I did was I didn't want to map the file name directly to the file asset and didn't want to get too fancy given the audience Smiley
  • User profile image
    Thomas

    Hi All,
    I have a short question.
    Is it possible to change the Text of the Buttons during the runtime?

    After starting my App, the predefined contents of the buttons were shown fine.
    But I cannot re-load the Data.
    Do I have to set the IsDataLoaded to false again?
    Please give me a hint.
    Thank you!

  • User profile image
    Clint

    @Thomas: yup, just need a hook into that button.  From an event handler or a name on the element or searching the DOM.  https://channel9.msdn.com/Series/Windows-Phone-8-Development-for-Absolute-Beginners/Part-4-Introduction-to-XAML we covered doing this via the name

    How are you attempting to reload your data?  You should be able to alter the view model and it should just update automatically.  This is since our ViewModel uses INotifyPropertyChanged and our SoundGroup collections are ObservableCollections. 

    All we do is validate should the data be loaded on the OnNavigatedTo in MainPage.Xaml.cs

  • User profile image
    Clint

    @Thomas: if you want to test stuff out, download our known working sample and try altering that code a bit as well.

  • User profile image
    Graham

    I'm just starting out, learning Windows Phone 8 development and I'm enjoying following this tutorial so far. I'm confused though, as to why there's a need for a 'IsDataLoaded' property. Would it not be better to have a constructor in the 'SoundModel' class, which calls 'LoadData()'? That way the data will always be loaded at object creation time, and there won't be any need to worry about timing issues. Also... (and I'm not being facetious) but don't you think property names should read more like a statement than a question? eg. I personaly think that 'IsDataLoaded' should be 'DataIsLoaded' which make statements like 'if(!DataIsLoaded)' more logical. Please tell me if I'm being petty.

  • User profile image
    Clint

    @Graham: depends how you want to do it.  Think about an application where it loads data from an external source.

    Also what if you want to use this class for something else?  You have data being loaded into it every time even though you don't want it.

    For naming, I was following the naming convention for .Net / c#.  IsEnabled, IsClosed, IsReadOnly, HasLoggedErrors, HasRows, ... makes it easier when reading a full statement as a question and just by the leading "Is", I know it will return a Boolean.  Allows for grouping of members as well in the object viewer dropdown.

  • User profile image
    Graham

    @Clint: Thanks for your response. I can see your point with regards the loading in the constructor, I was being a little blinkered in my approach, though it does work without the need for the 'viewModel.LoadData();' entry. As for the naming convention, you have exposed my naivety with regards the .net/c# naming conventions, which I am reasonably new to. Great series though, I am very grateful for tutorials such as this so please keep up the good work.

  • User profile image
    L Cat

    I have learned much by these tutorials. Thanks. Question about VisualStudio2012:if there would be issued VisualStudio for 64 bit computor in the near future? But WindowPhone does not have a bit issues, isn´t that so?

  • User profile image
    Clint
    @L Cat: I am confused by your question. Vs works on windows in 64 bit.
  • User profile image
    Kian

    Hello. i want to know how to store data and fetch that data for my app.

  • User profile image
    Clint
  • User profile image
    John

    First thanks for this series. This is has been really helpful to get me started on Windows Phone development.

    I have been a programmer for a long time and have way too much C/C++/C# experience and a few MSFT certs.... but this is making me feel stupid :(

    I am having trouble getting binding to work. If I bind to an entire ObservableCollection, I get nothing on the screen. If I bind to the 1st occurrence of the collection [0], I get that bit of data, but as you would expect no other data.

    These are my two class declarations

    using System.Collections.ObjectModel;
    using System.ComponentModel;

    namespace ReportFactors
    {
    public class Report : ObservableCollection<Factors>
    {
    public ObservableCollection<Factors> MyItems;

    public Report()
    {
    MyItems = new ObservableCollection<Factors>();
    }

    //public ObservableCollection<Factors> MyItems { get; private set; }

    public void LoadDefaultData()
    {
    MyItems.Add(new Factors("string1", "string2", "string3", "string4"));
    MyItems.Add(new Factors("string5", "string6", "string7", "string8"));

    }
    }

    public class Factors : INotifyPropertyChanged
    {
    private string _fcDate;
    private string _fcIconURL;
    private string _fcTitle;
    private string _fcText;

    public Factors (string fcdate, string title, string fctext, string iconurl)
    {
    fcDate = fcdate;
    fcText = fctext;
    fcIconURL = iconurl;
    fcTitle = title;
    }

    public string fcDate
    {
    get {return _fcDate;}
    set {if (value != _fcDate){_fcDate = value; NotifyPropertyChanged("fcDate");}}
    }

    public string fcIconURL
    {
    get { return _fcIconURL; }
    set {if (value != _fcIconURL){_fcIconURL = value; NotifyPropertyChanged("fcIconURL");}}
    }

    public string fcTitle
    {
    get { return _fcTitle; }
    set { if (value != _fcTitle) {_fcTitle = value; NotifyPropertyChanged("fcTitle");}}
    }

    public string fcText
    {
    get { return _fcText; }
    set { if (value != _fcText) {_fcText = value; NotifyPropertyChanged("fcText");}}
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string property)
    {
    if (PropertyChanged != null)
    {
    PropertyChanged(this, new PropertyChangedEventArgs(property));
    }
    }
    }
    }

    The Report constructor creates the ObservableCollection of Factors and assigns that to MyItems. The Report class also contains a LoadDefaultData method which Adds some hard coded data.

    I am setting DataContext = App.report.MyItems in the MainPage constructor in MainPage.xaml.cs

    At this point I am absolutely certain that I have made a bonehead mistake but I have been looking at this for so long that I can't see it.

    Any help would be helpful and welcome. Thanks for your time.

    John

  • User profile image
    Clint

    @John: Hey John, we can only really support questions related to the series. I'd ask this question on the forums over at https://dev.windowsphone.com or www.stackoverflow.com

    Sorry

  • User profile image
    john

    No worries. Thanks for the redirect

  • User profile image
    shubham kumar

    I have watched till Part 15 tutorial.The problem is in SDK the MainPage.xaml shows all three pivot items(I've just implemented 3) animals,cartoons and custom sounds but while running it on emulator it shows only one pivot item -'animals'.I've closely watched videos and checked the code.Please help.What could be wrong ?

  • User profile image
    Clint

    @shubham kumar: The first thing I would try to do is right click on the solution and use "clean solution" then try to redeploy.  If that doesn't fix it create a bug and upload solution minus the Bin, Obj, and Asset folder to https://absolutebeginner.codeplex.com/WorkItem/Create and I will take a look

  • User profile image
    ZhiLi

    I`ve tried many times to load data from SampleData.xml at RUN - Time(change the run time approach to utilize the file of data we already are using for design time.) as a challenge for me,but I failed to do that . I`m so confused .

    Could you give me some clues to complete that?

  • User profile image
    laiwayne

    I am trying to load the xaml file in C#, I am getting this Error,
    'System.IO.DirectoryNotFoundException'
    It seems like it's not finding the SampleData.xaml,
    The error says that path points to C:\Data\Programs\{8DDBDFC0-E495-4D59-ABD0-52877691D4FE}\Install\SampleData\RunData.xaml
    and I can't find C:\Data actually. Am I missing anything here?

    private void LoadXaml() {
    string path = @".\SampleData\SampleData.xaml";
    StreamReader reader = new StreamReader(path);
    }

  • User profile image
    laiwayne

    Figured that I have to make the Build Action property of SampleData.xaml as content, and also need to add "assembly=SoundBoard" on the top of xaml.
    xmlns:vm="clr-namespace:SoundBoard.ViewModels;assembly=SoundBoard

    is there a reason that I need to add that? since this xaml is included in the assembly already.

  • User profile image
    Clint

    @ZhiLi: that is outside the scope of the lesson here.  If memory serves, you can't alter a file like that, you'll need to save it to isolated storage

  • User profile image
    Joe

    I have a question about the challenge. Is the goal to use the same file at design time and run time?

  • User profile image
    BobTabor

    @Joe: Yes, instead of creating C# objects at runtime, use same XAML (XML) file at RUNTIME that we're using for design time.

  • User profile image
    nighilanth

    @BobTabor:Hey Bob,

    I finished your series and absolutely love it. I started an app similar to PetSounds, I retraced all steps until lesson 14 but for some reason I can't get data showing at runtime. I checked all ModelView methods and they are working, Load data working also but at some point, when I bind Datacontext to model view, DataContext doesn't get any info. I suspect that it has something to do with async methods in my code because I used HTML string to pull data from website. I trying to resolve it for 2 days and no luck. If you have 10 minutes of your time and look at my project which I uploaded to https://cineman.codeplex.com/ it will be much appreciated.

  • User profile image
    BobTabor

    @nighilanth: I'm really sorry, I'm simply too busy to commit to that.  You may want to ask for help on MSDN's forums ... maybe someone there can spot the issue: 

    https://social.msdn.microsoft.com/Forums/en-US/home?forum=wpdevelop&filter=alltypes&sort=lastpostdesc

  • User profile image
    nighilanth

    @BobTabor: That's alright:) I will probably resolve this by myself :). Thanks anyway! 

  • User profile image
    nighilanth

    Nailed it:) 

    needed to await LoadData before assigning DataContext.

  • User profile image
    BobTabor

    @nighilanth: Nice, great job figuring it out!!!  [H]

  • User profile image
    JosepW

    Very nice series! Thank you!
    In case it may help, I created this helper method to avoid too much typing:
    private static List<SoundData> GetSoundData(string path)
    {
    try
    {
    return Directory.GetFiles("Assets/Audio/" + path + "/").
    Where(f => f.EndsWith(".wav")).
    Select(p => new SoundData
    {
    Title = Path.GetFileNameWithoutExtension(p),
    FilePath = p
    }).ToList();
    }
    catch (DirectoryNotFoundException)
    {
    return new List<SoundData>();
    }
    }

    It can be used this way (I wanted to keep Title decoupled from the subpath name):
    Animals = new SoundGroup
    {
    Title = "animals",
    Items = GetSoundData("Animals")
    };

  • User profile image
    Joachim David

    I finally figured it out and got the XAML file to load into my app at runtime.
    The hardest part was figuring out why the xaml file just couldn't be loaded, the remedy is setting the build action of the SampleData.xaml file to content, what exactly does this do?

  • User profile image
    BobTabor

    @Joachim David: See here: https://msdn.microsoft.com/en-us/library/0c6xyb66(v=vs.100).aspx

    We don't need that XAML to be compiled into a .NET assembly.  Remember back to the beginning of the series ... XAML can be used to create instances of types.  HOWEVER in this case, we're using it to represent just data that we'll load into our app.  We could have used other formats (JSON, comma delimited, plain ol' XML).  This just demo'd another way.  I think I instructed you to set the type of Content in another video.  Maybe you missed it?

  • User profile image
    Sam

    Bob do you have any idea how to save camera capture image in sqlite database and how to show in the next page and where the camera image path is save

  • User profile image
    Sherif

    Thanks for this amazing series ...

    i have been trying to solve this error for a while...

    when i build solution it says that Build succeeded ,But when running the App on Emulator it Stops and gives me Unhandled exception and here is the details of it ..

    >>>
    System.NullReferenceException was unhandled by user code
    HResult=-2147467261
    Message = Object reference not set to an instance of an object.
    Source=Recorder
    StackTrace:
    at Recorder.ViewModels.SoundModel.CreateAnimalsGroup()
    at Recorder.ViewModels.SoundModel.LoadData()
    at Recorder.App.get_ViewModel()
    at Recorder.MainPage..ctor()
    InnerException:
    <<<<<<<<<<

    I googled for a while but without any results ... !!

    can anyone Help me to Solve this issue ?!

  • User profile image
    BobTabor

    @Sherif: That usually means you're attempting to use an instance of a class before you created the new instance.  I recommend putting a break point in the constructor or the methods that are used first in that class and walking through until you hit the error looking for where an instance of that class was new'd up.  Good luck.

  • User profile image
    Bivo

    Hi,

    There is something that I'm missing and can't figure out where you mention it.
    I the prev. lesson, when you introduced the ViewModel concept you showed how to
    you a Observable collection for the data binding of a list.

    In this lesson you switched from the static data binding (of the XAML data) to a run time approach. But where do you specify to bind the items source of every LongListSelector to one of the "Groups" you define?

  • User profile image
    Fagun Rain

    The navigation bar is not coming. I have added viewModel.LoadData() in the condition. But still now not getting the navigation bar. And I am little bit confuse about you debugging.

  • User profile image
    ChuckJ

    I like how this app was done but is there any possible way to implement a saveringtonetask in the same manner, where it will automatically create the tile/button?
    Or if not, how about the same thing you have going on with the sound tiles, but implement a HOLD gesture to save as ringtone on the same button that plays the sound?

  • User profile image
    ChuckJ

    Forget my above question. I added a Context Menu to the DataTemplate that would give the option to Save as Ringtone if you press and hold on the Tile. It works....BUT only when I specify an audio file in the mainpage.cs. How can I write the code below in a way that it will use the same source as the Tile you press, just like the playing sound does? Is there anything specific I can put in the source that will do this?

    private void Save_Click(object sender, System.Windows.RoutedEventArgs e)
    {
    _CustomRingtone.Source = new Uri(WHAT GOES HERE);
    _CustomRingtone.DisplayName = "Ring";
    _CustomRingtone.Show();

  • User profile image
    JeffreyFG

    When I run the App I get an error saying inconsistent Accessibility. Its for the ViewModel property. I have directly copied the code from the source code so I don't think is has to do with that file. What I am I missing.

Add Your 2 Cents