Simple two way data binding to a model's property is not working, to reproduce the issue, I have created a new project in Visual Studio 2013 i.e. with Blank App (Universal Apps) template with .NET framework 4.5
Project folders and files
The model
namespace UWP.MVVM.Models
{
public class PersonModel
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
The base view model
namespace UWP.MVVM.Core
{
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class VMBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
The INavigable interface
namespace UWP.MVVM.Core
{
#if WINDOWS_PHONE_APP
using Windows.Phone.UI.Input;
#endif
public interface INavigable
{
void Activate(object parameter);
void Deactivate(object parameter);
#if WINDOWS_PHONE_APP
void BackButtonPressed(BackPressedEventArgs e);
#endif
}
}
The main view model
namespace UWP.MVVM.ViewModels
{
using UWP.MVVM.Core;
using UWP.MVVM.Models;
#if WINDOWS_PHONE_APP
using Windows.Phone.UI.Input;
#endif
public class MainViewModel : VMBase, INavigable
{
private PersonModel person;
public MainViewModel()
{
this.Person = new PersonModel();
}
public PersonModel Person
{
get
{
return this.person;
}
set
{
if (value == this.person)
{
return;
}
this.person = value;
this.NotifyPropertyChanged();
}
}
public void Activate(object parameter)
{
this.Person.FirstName = "Gerrard";
}
public void Deactivate(object parameter)
{
}
#if WINDOWS_PHONE_APP
public void BackButtonPressed(BackPressedEventArgs e)
{
}
#endif
}
}
The main page view
<Page
x:Class="UWP.MVVM.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWP.MVVM"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:UWP.MVVM.ViewModels"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<!--<Page.DataContext>
<vm:MainViewModel/>
</Page.DataContext>-->
<Grid Margin="24,24">
<TextBox Header="First Name"
Text="{Binding Person.FirstName}"/>
</Grid>
</Page>
The main page code behind
namespace UWP.MVVM
{
using UWP.MVVM.Core;
#if WINDOWS_PHONE_APP
using Windows.Phone.UI.Input;
#endif
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using UWP.MVVM.ViewModels;
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
this.DataContext = new MainViewModel();
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached.
/// This parameter is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
var navigableViewModel = this.DataContext as INavigable;
if (navigableViewModel != null)
{
navigableViewModel.Activate(e.Parameter);
}
#if WINDOWS_PHONE_APP
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
#endif
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
var navigableViewModel = this.DataContext as INavigable;
if (navigableViewModel != null)
{
navigableViewModel.Deactivate(e.Parameter);
}
#if WINDOWS_PHONE_APP
HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
#endif
}
#if WINDOWS_PHONE_APP
private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
var navigableViewModel = this.DataContext as INavigable;
if (navigableViewModel != null)
{
navigableViewModel.BackButtonPressed(e);
}
}
#endif
}
}
I tried using Mode=TwoWay on the TextBox and it is not working, but when I set the DataContext in xaml instead of the code behind then data binding works even without the Mode=TwoWay property.
I want to set the DataContext in the code behind file as in the real project where I am having this issue, I am using MVVM-light libraries along with its SimpleIoc container, so I want to get the view model instance from SimpleIoc and set the DataContext because the view model dependencies are injected by the SimpleIoc and the code will be a lot cleaner.
The problem is: you only notify the change of PersonModel Person. The ViewModel need to notify the change of the property of PersonModel.
Since you are using MVVM Light, change your Model to:
public class PersonModel : ObservableObject
{
public int Id { get; set; }
string _FirstName = "";
public string FirstName {
get {
return _FirstName;
}
set {
Set(ref _FirstName, value);
}
}
public string LastName { get; set; }
}
Related
im working with custon entry rendered, i need to hear from xaml in my custom render when i clicked my button
i have this code in my xaml
<local:MyEntry eventRefresh="true">
when i clicked my button this function is actived
private async void Execute(object sender)
{
var entry = ((MyEntry)view);
entry.eventRefresh = "false";
but my EntryRendered donot hear the change
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var element = Element as MyEntry;
You should define the property eventRefresh as Bindable Property .
in your custom Entry
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Xamarin.Forms;
namespace xxx
{
public class MyEntry:Entry,INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public static readonly BindableProperty eventRefreshProperty = BindableProperty.Create("eventRefresh", typeof(bool), typeof(MyEntry), true,propertyChanged:(obj,oldValue,newValue)=> {
//var entry = obj as MyEntry;
// entry.Text = newValue.ToString();
});
bool refresh;
public bool eventRefresh
{
get { return refresh; }
set {
if(refresh !=value)
{
refresh = value;
NotifyPropertyChanged("eventRefresh");
}
}
}
public MyEntry()
{
}
}
}
in xaml
<StackLayout VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<local:MyEntry eventRefresh="{Binding Refresh}" BackgroundColor="{Binding BGcolor}" WidthRequest="200" HeightRequest="50" />
<Button Command="{Binding ClickCommand}" />
</StackLayout>
in View Model
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Color color;
public Color BGcolor
{
get { return color; }
set
{
if (color != value)
{
color = value;
NotifyPropertyChanged("BGcolor");
}
}
}
bool refresh;
public bool Refresh
{
get { return refresh; }
set
{
if (refresh != value)
{
refresh = value;
NotifyPropertyChanged("Refresh");
}
}
}
public ICommand ClickCommand { get; set; }
public MyViewModel()
{
BGcolor = Color.LightPink;
ClickCommand = new Command(()=> {
BGcolor = Color.Red;
});
}
}
in Custom Renderer
using System.ComponentModel;
using Android.Content;
using xxx;
using xxx.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly:ExportRenderer(typeof(MyEntry),typeof(NyEntryRenderer))]
namespace xxx.Droid
{
public class NyEntryRenderer : EntryRenderer
{
public NyEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Element.TextChanged += Element_TextChanged;
}
}
private void Element_TextChanged(object sender, TextChangedEventArgs e)
{
// var content = Element.Text;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == MyEntry.BackgroundColorProperty.PropertyName)
{
// will been invoked when click button
}
}
}
}
Make your view model like this.
public class YourViewModel
{
public Command command
{
get
{
return new Command(() => {
//Change here button background colors
BackgroundColor = Color.Green;
});
}
}
private _backgroundColor = Color.White;
public Color BackgroundColor
{
get { return _backgroundColor;}
set
{
if (value == _backgroundColor)
return;
_backgroundColor = value;
NotifyOnPropertyChanged(nameof(BackgroundColor));
}
}
}
Your XAML
<local:MyEntry Text="{Binding Password}" Placeholder="Enter" />
<Button Text="send" Command="{Binding command}" BackgroundColor="{Binding BackgroundColor}"></Button>
I have tab pages implementing different views, but I cannot initialize each of the tabs when navigating.
<TabbedPage.Children>
<tabPages:Page1/>
<tabPages:Page2/>
<tabPages:Page3/>
</TabbedPage.Children>
So what I did was to use IActiveAware as prism documentation suggested to know which tab page is currently active. So I have this class:
public abstract class TabbedChildViewModelBase : BaseViewModel, IActiveAware, INavigationAware, IDestructible
protected bool IsInitalized { get; set; }
private bool _IsActive;
public bool IsActive
{
get
{
return _IsActive;
}
set
{
SetProperty(ref _IsActive, value, RaiseIsActiveChanged);
}
}
public event EventHandler IsActiveChanged;
public virtual void OnNavigatingTo(NavigationParameters parameters)
{
}
protected virtual void RaiseIsActiveChanged()
{
IsActiveChanged?.Invoke(this, EventArgs.Empty);
}
public virtual void Destroy()
{
}
}
So each child view models inherits the child view model base:
public class Page1 : TabbedChildViewModelBase
{
public CurrentSeaServiceViewModel()
{
IsActiveChanged += HandleIsActiveTrue;
IsActiveChanged += HandleIsActiveFalse;
}
private void HandleIsActiveTrue(object sender, EventArgs args)
{
if (IsActive == false)
{
TestLabelOnly = "Test";
}
// Handle Logic Here
}
private void HandleIsActiveFalse(object sender, EventArgs args)
{
if (IsActive == true) return;
// Handle Logic Here
}
public override void Destroy()
{
IsActiveChanged -= HandleIsActiveTrue;
IsActiveChanged -= HandleIsActiveFalse;
}
}
The problem is, the child vm isn't initializing. Is there something needed in order to implement IActiveAware properly nor launching the IsActive property
I still used IActiveAware unfortunately, to make the childtabbedviewmodel work you need to bind the page to its own view model.
So here's what I did:
<TabbedPage.Children>
<views:ChildPage1>
<views:ChildPage1.BindingContext>
<viewModels:ChildPage1ViewModel/>
</views:ChildPage1.BindingContext>
</views:ChildPage1>
<views:ChildPage2>
<views:ChildPage2.BindingContext>
<viewModels:ChildPage2ViewModel/>
</views:ChildPage2.BindingContext>
</views:ChildPage2>
</TabbedPage.Children>
I used the property BindingContext of my views and
using IActiveAware I would also know what tab is currently active. Hope anyone helps this who finds trouble binding the child pages of a tab.
like the title says I want to give through the user information to my viewmodel, but the problem is that the viewmodel is registered as a dependency and I am binding its content to the xaml page itself. How do I send the user information to the viewmodel itself?
Thank you!
Xaml.cs part:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Calendar : ContentPage
{
public Calendar(User user)
{
InitializeComponent();
FileImageSource image = new FileImageSource
{
File = "calendar.png"
};
Icon = image;// push user information to the ICalendarViewModel
BindingContext = AppContainer.Container.Resolve<ICalendarViewModel>();
}
}
Interface:
public interface ICalendarViewModel : INotifyPropertyChanged
{
}
Bootstrap part registering dependencies:
public class Bootstrap
{
public IContainer CreateContainer()
{
var containerBuilder = new ContainerBuilder();
RegisterDependencies(containerBuilder);
return containerBuilder.Build();
}
protected virtual void RegisterDependencies(ContainerBuilder builder)
{
builder.RegisterType<CalendarViewModel>()
.As<ICalendarViewModel>()
.SingleInstance();
}
}
CalendarViewModel: I do not know if this will help
public class CalendarViewModel : ViewModelBase, ICalendarViewModel
{
public event PropertyChangedEventHandler PropertyChanged;
public string ErrorMessage { get; set; }
private CourseInformation _information;
private ICourseInformationRepository _repository;
public CalendarViewModel()
{
_repository = new CourseInformationRepository();
LoadData();
}
private ObservableCollection<CourseInformation> _courses;
public ObservableCollection<CourseInformation> Courses
{
get
{
return _courses;
}
set
{
_courses = value;
RaisePropertyChanged(nameof(Courses));
}
}
private void LoadData()
{
try
{
ObservableCollection<CourseInformation> CourseList = new ObservableCollection<CourseInformation>(_repository.GetAllCourseInformation());
Courses = new ObservableCollection<CourseInformation>();
DateTime date;
foreach (var course in CourseList)
{
string [] cour = course.Date.Split('/');
cour[2] = "20" + cour[2];
date = new DateTime(Convert.ToInt32(cour[2]), Convert.ToInt32(cour[1]), Convert.ToInt32(cour[0]));
if (date == DateTime.Now)//TESTING WITH TEST DATE, datetime.now
{
if (course.FromTime.Length < 4)
{
course.FromTime = "0" + course.FromTime;
}
if (course.UntilTime.Length < 4)
{
course.UntilTime = "0" + course.UntilTime;
}
course.FromTime = course.FromTime.Insert(2, ":");
course.UntilTime = course.UntilTime.Insert(2, ":");
Courses.Add(course);
}
}
}
catch (ServerUnavailableException e)
{
ErrorMessage = "Server is niet beschikbaar, ophalen van kalender is niet mogelijk.";
}
}
private void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Bootstrap binding in app.xaml.cs:
public partial class App : Application
{
public App()
{
InitializeComponent();
AppContainer.Container = new Bootstrap().CreateContainer();
MainPage = new LoginView();
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
I wanted to comment (not enough reputation) on #LeRoy, use a framework. I would recommend FreshMVVM and you can pass objects into the ViewModel and even pass in Services. It makes it all nice and clean, and it just works.
Should not your CalendarViewModel viewModel contain BindableBase ?
public class CalendarViewModel : BindableBase, ViewModelBase, ICalendarViewModel
what framework are you using? prism, freshmvvm.
Your View and Viewmodel is normally automatically handled by the framework, all you need to do is register your page.
Container.RegisterTypeForNavigation<Views.CalendarPage>();
I am developing Windows Phone app and I've got this issue:
I have a list control which displays my search results, but when the keyboard is opened some of my results aren't visible because of my keyboard...
Is there a way to shrink the control till keyboard border? In order to see all the results.
I want to scroll till the end of the results even when the keyboard is opened.
There is my solution
public class ResizeContentOnKeyboardShowingBehavior : Behavior<Page>
{
private readonly double _screenHeight;
public ResizeContentOnKeyboardShowingBehavior()
{
_screenHeight = Window.Current.Bounds.Height;
}
protected override void OnAttached()
{
InputPane.GetForCurrentView().Showing += OnKeyboardShowing;
InputPane.GetForCurrentView().Hiding += OnKeyboardHiding;
}
protected override void OnDetaching()
{
InputPane.GetForCurrentView().Showing -= OnKeyboardShowing;
InputPane.GetForCurrentView().Hiding -= OnKeyboardHiding;
}
private void OnKeyboardHiding(InputPane sender, InputPaneVisibilityEventArgs args)
{
var content = (FrameworkElement)AssociatedObject.Content;
content.Height = _screenHeight;
}
private void OnKeyboardShowing(InputPane sender, InputPaneVisibilityEventArgs args)
{
var content = (FrameworkElement)AssociatedObject.Content;
double keyboardHeight = sender.OccludedRect.Height;
content.Height = _screenHeight - keyboardHeight;
}
}
Base Behavior implementation:
public abstract class Behavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; set; }
public virtual void Attach(DependencyObject associatedObject)
{
AssociatedObject = associatedObject;
}
public virtual void Detach()
{
}
}
public abstract class Behavior<T> : Behavior
where T : DependencyObject
{
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public new T AssociatedObject { get; set; }
public override void Attach(DependencyObject associatedObject)
{
base.Attach(associatedObject);
this.AssociatedObject = (T)associatedObject;
OnAttached();
}
public override void Detach()
{
base.Detach();
OnDetaching();
}
protected virtual void OnAttached()
{
}
protected virtual void OnDetaching()
{
}
}
IBehavior interface is from Microsoft.Xaml.Interactivity namespace from Behaviors SDK http://scr.hu/4m4q/pzl07
Usage:
<Page x:Class="MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:behaviors="using:Behaviors">
<interactivity:Interaction.Behaviors>
<behaviors:ResizeContentOnKeyboardShowingBehavior />
</interactivity:Interaction.Behaviors>
<Grid>
</Grid>
Or the same functionality but without behavior. Just added to page code behind.
public sealed partial class MainPage : Page
{
private readonly InputPane _inputPane;
private readonly double _screenHeight;
public MainPage()
{
this.InitializeComponent();
_screenHeight = Window.Current.Bounds.Height;
_inputPane = InputPane.GetForCurrentView();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_inputPane.Hiding += OnKeyboardHiding;
_inputPane.Showing += OnKeyboardShowing;
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
_inputPane.Hiding -= OnKeyboardHiding;
_inputPane.Showing -= OnKeyboardShowing;
}
private void OnKeyboardShowing(InputPane sender, InputPaneVisibilityEventArgs args)
{
var content = (FrameworkElement)Window.Current.Content;
double keyboardHeight = sender.OccludedRect.Height;
content.Height = _screenHeight - keyboardHeight;
}
private void OnKeyboardHiding(InputPane sender, InputPaneVisibilityEventArgs args)
{
var content = (FrameworkElement)Window.Current.Content;
content.Height = _screenHeight;
}
}
I created a WP Class Library BusinessLogic project which is composed by these three class
1) Bottle Class
namespace BusinessLogic
{
public class Bottle : INotifyPropertyChanged
{
// Due to INotifyPropertyChanged interface
public event PropertyChangedEventHandler PropertyChanged;
// Proprietà Title
private string title;
public string Title
{
set
{
if (title != value)
{
title = value;
OnPropertyChanged("Title");
}
}
get
{
return title;
}
}
// Proprietà PhotoFileName
private string photoFileName;
public string PhotoFileName
{
set
{
if (photoFileName != value)
{
photoFileName = value;
OnPropertyChanged("PhotoFileName");
}
}
get
{
return photoFileName;
}
}
protected virtual void OnPropertyChanged(string propChanged)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propChanged));
}
}
}
2) Bottles Class
namespace BusinessLogic
{
public class Bottles : INotifyPropertyChanged
{
// Due to INotifyPropertyChanged interface
public event PropertyChangedEventHandler PropertyChanged;
// Proprietà MainTitle
private string mainTitle;
public string MainTitle
{
set
{
if (mainTitle != value)
{
mainTitle = value;
OnPropertyChanged("MainTitle");
}
}
get
{
return mainTitle;
}
}
// Proprietà bottles
private ObservableCollection<Bottle> bottleSet = new ObservableCollection<Bottle>();
public ObservableCollection<Bottle> BottleSet
{
set
{
if (bottleSet != value)
{
bottleSet = value;
OnPropertyChanged("BottleSet");
}
}
get { return bottleSet; }
}
protected virtual void OnPropertyChanged(string propChanged)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propChanged));
}
}
}
3) BottlesPresenter Class
namespace BusinessLogic
{
public class BottlesPresenter : INotifyPropertyChanged
{
// Due to INotifyPropertyChanged interface
public event PropertyChangedEventHandler PropertyChanged;
// Proprietà BottleMatrix
private Bottles bottlesMatrix;
public Bottles BottlesMatrix
{
protected set
{
if (bottlesMatrix != value)
{
bottlesMatrix = value;
OnPropertyChanged("BottlesMatrix");
}
}
get { return bottlesMatrix; }
}
public BottlesPresenter()
{
XmlSerializer xml = new XmlSerializer(typeof(Bottles));
using (StreamReader fileReader = new StreamReader(#"C:\Stuff\WindowsPhone\AppLearningHowTo2\AppLearningHowTo2\DAL\DB.xml"))
{
BottlesMatrix = (Bottles)xml.Deserialize(fileReader);
}
}
protected virtual void OnPropertyChanged(string propChanged)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propChanged));
}
}
}
The BottlePresenter constructor should deserialize from an xml file located into the file system. It contains the following tags
<?xml version="1.0"?>
<Bottles xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MainTitle>MainTitle</MainTitle>
<Bottleset>
<Bottle>
<Title>Title1</Title>
<PhotoFileName>PhotoFileName1</PhotoFileName>
</Bottle>
<Bottle>
<Title>Title2</Title>
<PhotoFileName>PhotoFileName2</PhotoFileName>
</Bottle>
</Bottleset>
</Bottles>
Then I created a WP Application and I made a reference to the BusinessLogic.dll project library.
In the MainPage.xaml file I put the XML namespace declaration
xmlns:businesslogic="clr-namespace:BusinessLogic;assembly=BusinessLogic"
I then instantiated the BottlesPresenter class in the MainPage.xaml Resources collection
<phone:PhoneApplicationPage.Resources>
<businesslogic:BottlesPresenter x:Key="bottlesPresenter" />
</phone:PhoneApplicationPage.Resources>
And finally put a TextBlock in the content area with a binding to that resource:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Source={StaticResource bottlesPresenter},
Path=Bottles.MainTitle}" />
Unfortunately I launch the debugger, the emulator switch on, reach the splashscreen and doesn't go on.
In a nutshell: I can't reach to create an instance of the BottlesPresenter class.
I banged my head against the wall for weeks without finding a solution.
Please could someone give me a hand?
Thank you very much
Antonio
Emulator behaves like that when WP7 cannot construct Application object. From question, I see only 1 reference from Application to your code. It's BottlePresenter in Resources.
XamlLoader tries to create instance of this type.
See what's inside your BottlePresenter constructur:
public BottlesPresenter()
{
XmlSerializer xml = new XmlSerializer(typeof(Bottles));
using (StreamReader fileReader = new StreamReader(
#"C:\Stuff\WindowsPhone\AppLearningHowTo2\AppLearningHowTo2\DAL\DB.xml"))
{
BottlesMatrix = (Bottles)xml.Deserialize(fileReader);
}
}
First line is OK.
Second line is OK.
Third line causes exception, because path "C:\Stuff\WindowsPhone\AppLearningHowTo2\AppLearningHowTo2\DAL\DB.xml" is not acceptable on Windows Phone.
All files you can access is Content of your XAP, Resources in your assembly, and files in Isolated Storage.
Following articles might help you All about WP7 Isolated Storage - Read and Save Text files