I'm developing a Silverlight WP7 app using MVVM Light Toolkit which initially works properly. For each View I set its DataContext in the codebhind of the View using the following code:
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
DataContext = ViewModelLocator.MainPageViewModelStatic;
}
}
My ViewModelLocator is declared at the App.xaml file
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />
</Application.Resources>
Eventhough when I try to set the datacontext within the xaml instead of do it this within the codebehind I get an error.
This is the codebehind:
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
//DataContext = ViewModelLocator.MainPageViewModelStatic;
}
}
This is the final XAML:
<phone:PhoneApplicationPage
x:Class="Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:au="clr-namespace:AppBarUtils;assembly=AppBarUtils"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="696"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True"
DataContext="{Binding MainPageViewModel, Source={StaticResource Locator}}">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
</Grid>
<!--Sample code showing usage of ApplicationBar-->
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" BackgroundColor="{StaticResource PhoneAccentColor}">
<shell:ApplicationBarIconButton IconUri="/Resources/Icons/appbar.check.rest.png" Text="Iniciar" />
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="Iniciar" />
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
<i:Interaction.Behaviors>
<au:AppBarItemCommand
ItemText="Iniciar" Command="{Binding IniciarSesion}" />
</i:Interaction.Behaviors>
</phone:PhoneApplicationPage>
This is my ViewModel:
namespace ViewModels
{
public class MainPageViewModel : ViewModelBase
{
public const string mensajePropertyName = "mensaje";
private string _mensaje = "";
public string mensaje
{
get
{
return _mensaje;
}
set
{
if (_mensaje == value)
{
return;
}
var oldValue = _mensaje;
_mensaje = value;
RaisePropertyChanged(mensajePropertyName);
}
}
private RelayCommand _iniciarSesion;
public RelayCommand IniciarSesion
{
get
{
if (_iniciarSesion == null)
{
_iniciarSesion=new RelayCommand((()=> this.mensaje="hola"));
}
return _iniciarSesion;
}
}
}
}
A clue is that if I remove the AppBarItemCommand binding and I add more controls with bindings to other properties in the viewmodel the app runs without problems. The problem appears just when I set the binding for the AppBarItemCommand.
This is the stack trace the exception returns:
at AppBarUtils.AppBarItemCommand.ChangeIsEnabled()
at AppBarUtils.AppBarItemCommand.OnCommandChanged(DependencyPropertyChangedEventArgs e)
at AppBarUtils.AppBarItemCommand.CommandPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.RaisePropertyChangeNotifications(DependencyProperty dp, Object oldValue, Object newValue)
at System.Windows.DependencyObject.UpdateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)
at System.Windows.DependencyObject.RefreshExpression(DependencyProperty dp)
at System.Windows.Data.BindingExpression.RefreshExpression()
at System.Windows.Data.BindingExpression.SendDataToTarget()
at System.Windows.Data.BindingExpression.SourceAcquired()
at System.Windows.Data.BindingExpression.InheritanceContextChanged(Object sender, EventArgs e)
at System.Windows.DependencyObject.OnInheritanceContextChanged(Object sender, EventArgs e)
at System.Windows.DOCollection.AddInternal(DependencyObject value)
at System.Windows.PresentationFrameworkCollection`1.Add(DependencyObject value)
at System.Windows.DependencyObjectCollection`1.System.Collections.IList.Add(Object value)
at MS.Internal.XamlManagedRuntimeRPInvokes.Add(XamlQualifiedObject& qoCollection, XamlPropertyToken inCollectionProperty, XamlQualifiedObject& inValue)
at MS.Internal.XcpImports.Application_LoadComponentNative(IntPtr pContext, IntPtr pComponent, UInt32 cUriStringLength, String uriString, UInt32 cXamlStrLength, Byte* pXamlStr, UInt32 cAssemblyStrLength, String assemblyStr)
at MS.Internal.XcpImports.Application_LoadComponent(IManagedPeerBase componentAsDO, String resourceLocator, UnmanagedMemoryStream stream, UInt32 numBytesToRead, String assemblyString)
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at PCCOM.Distrib.Presentation.PreventaClient.Views.MainPage.InitializeComponent()
at PCCOM.Distrib.Presentation.PreventaClient.Views.MainPage..ctor()
at System.Reflection.RuntimeConstructorInfo.InternalInvoke(RuntimeConstructorInfo rtci, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
at System.Reflection.RuntimeConstructorInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
at System.Activator.InternalCreateInstance(Type type, Boolean nonPublic, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type)
at System.Windows.Navigation.PageResourceContentLoader.BeginLoad_OnUIThread(AsyncCallback userCallback, PageResourceContentLoaderAsyncResult result)
at System.Windows.Navigation.PageResourceContentLoader.<>c__DisplayClass4.<BeginLoad>b__0(Object args)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at System.Delegate.DynamicInvokeOne(Object[] args)
at System.MulticastDelegate.DynamicInvokeImpl(Object[] args)
at System.Delegate.DynamicInvoke(Object[] args)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.Dispatch(DispatcherPriority priority)
at System.Windows.Threading.Dispatcher.OnInvoke(Object context)
at System.Windows.Hosting.CallbackCookie.Invoke(Object[] args)
at System.Windows.Hosting.DelegateWrapper.InternalInvoke(Object[] args)
at System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle, Int32 nParamCount, ScriptParam[] pParams, ScriptParam& pResult)
Any idea?
Thank you