DataBinding with MVVM Light tool kit - mvvm-light

I get some trouble with the binding using MVVM toolkit and would likr to knwo some advise if I do things correctly. First of all I have the View Model Locator which is defined as follow :
public class ViewModelLocator
{
private static MainViewModel _main;
private static ProductViewModel _product;
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
////if (ViewModelBase.IsInDesignModeStatic)
////{
//// // Create design time view models
////}
////else
////{
//// // Create run time view models
////}
CreateMain();
CreateProduct();
}
/// <summary>
/// Gets the Main property.
/// </summary>
public static MainViewModel MainStatic
{
get
{
if (_main == null)
{
CreateMain();
}
return _main;
}
}
/// <summary>
/// Gets the Main property.
/// </summary>
public static ProductViewModel ProductStatic
{
get
{
if (_product == null)
{
CreateProduct();
}
return _product;
}
}
/// <summary>
/// Gets the Main property.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return MainStatic;
}
}
/// <summary>
/// Gets the Main property.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public ProductViewModel Product
{
get
{
return ProductStatic;
}
}
/// <summary>
/// Provides a deterministic way to delete the Main property.
/// </summary>
public static void ClearMain()
{
_main.Cleanup();
_main = null;
}
/// <summary>
/// Provides a deterministic way to create the Main property.
/// </summary>
public static void CreateMain()
{
if (_main == null)
{
_main = new MainViewModel();
}
}
/// <summary>
/// Provides a deterministic way to create the Main property.
/// </summary>
public static void CreateProduct()
{
if (_product == null)
{
_product = new ProductViewModel();
}
}
/// <summary>
/// Cleans up all the resources.
/// </summary>
public static void Cleanup()
{
ClearMain();
}
}
Then I have my main window for which I set the datacontext as :
DataContext="{Binding Source={x:Static vm:ViewModelLocator.MainStatic}}"
Inside my main window I have a list box which will have as ItemSource a collection of ProductViewModel define as follow :
public class ProductViewModel : ViewModelBase
{
SvcProduct.ProductServiceClient _clientSvc =new SvcProduct.ProductServiceClient() ;
ObservableCollection<Product> _products = new ObservableCollection<Product>();
public ObservableCollection<Product> Products
{
get { return _products; }
set { _products = value; }
}
/// <summary>
/// Initializes a new instance of the ProductViewModel class.
/// </summary>
public ProductViewModel()
{
////if (IsInDesignMode)
////{
//// // Code runs in Blend --> create design time data.
////}
////else
////{
//// // Code runs "for real": Connect to service, etc...
////}
_products=_clientSvc.GetProducts();
}
////public override void Cleanup()
////{
//// // Clean own resources if needed
//// base.Cleanup();
////}
}
ProductViewModel return in Products the collection for the listbox. Each item in the list box is connected to a ProductView which is a userControl define as follow :
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Solatys.Presentation.ViewModel"
mc:Ignorable="d"
x:Class="Solatys.Presentation.ProductView"
x:Name="UserControl"
d:DesignWidth="640" d:DesignHeight="480" Width="433" Height="319"
IsManipulationEnabled="True"
DataContext="{Binding Source={x:Static vm:ViewModelLocator.ProductStatic}}">
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="144.3"/>
<ColumnDefinition Width="0.64*"/>
<ColumnDefinition Width="144.3"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="35" MaxHeight="35"/>
<RowDefinition Height="130" MaxHeight="130"/>
<RowDefinition Height="130" MaxHeight="130"/>
<RowDefinition Height="24" MaxHeight="24"/>
</Grid.RowDefinitions>
<Image Source="Resources/beauté.jpg" Grid.Row="1" Stretch="UniformToFill" Grid.RowSpan="2" Grid.ColumnSpan="3"/>
<TextBlock TextWrapping="Wrap" Grid.Column="1" Text="{Binding ProductName}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" Foreground="White" FontFamily="Perpetua Titling MT" TextAlignment="Justify"/>
<Border BorderBrush="Black" BorderThickness="0" Grid.Row="3" Grid.ColumnSpan="3">
<Border.Background>
<RadialGradientBrush>
<GradientStop Color="#00000000" Offset="1"/>
<GradientStop Color="#FF005E01"/>
</RadialGradientBrush>
</Border.Background>
<TextBlock TextWrapping="Wrap" Text="Coup de Coeur" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Perpetua" TextAlignment="Justify" FontSize="13.333"/>
</Border>
<Border Grid.Row="1" Grid.Column="0" Background="#7F000000" d:LayoutOverrides="Width">
<TextBlock TextWrapping="Wrap" Foreground="White" FontFamily="Perpetua" Margin="5"><Run Text="Type de produit"/><Run Language="fr-fr" Text=" : "/><LineBreak/><Run Language="fr-fr"/><LineBreak/><Run Language="fr-fr" Text="Produit de beauté Bio"/></TextBlock>
</Border>
<Border HorizontalAlignment="Right" Grid.Row="1" Grid.Column="2" Width="144.3" Height="130" Background="#7F000000">
<TextBlock Margin="5" TextWrapping="Wrap" Foreground="White" FontFamily="Perpetua"><Run Text="Court descriptif"/><LineBreak/><Run/><LineBreak/><Run Language="fr-fr" Text="Ce nouveau produit reste notre coup de coeur pour ses propriétés naturelles ..."/></TextBlock>
</Border>
<Border HorizontalAlignment="Center" Grid.Row="2" Grid.Column="1" Width="144.3" Height="130" Background="#7F000000">
<TextBlock TextWrapping="Wrap" Margin="5" Foreground="White" FontFamily="Perpetua"><Run Text="Caractéristiques du produit"/><Run Language="fr-fr" Text=" : "/><LineBreak/><Run Language="fr-fr"/><LineBreak/><Run Language="fr-fr" Text="- rajeunissant"/><LineBreak/><Run Language="fr-fr" Text="- vivifiant"/><LineBreak/><Run Language="fr-fr" Text="- prix attractif"/><LineBreak/><Run Language="fr-fr" Text="- produit contrôlé"/></TextBlock>
</Border>
</Grid>
As you can see the above the DataContext is set to ViewModelLocator.ProductStatic but it says an error like "Cannot create instance of ViewModelLocator"
Due to that it seems that the binding is not operating as my list box is empty on my main Window
1- Any idea what I do wrong for that error?
2- In my scenario, how should I bind the ItemSource as the collection is a collection of ProductViewModel ?
regards
serge

"Cannot create instance of ViewModelLocator" is typically a sign that something went wrong while the VMs were created. Try to put a breakpoint on _products=_clientSvc.GetProducts() then debug the code. I am pretty sure that something is going wrong in this method and an exception is thrown, which is causing the ViewModelLocator to fail too.
Cheers,
Laurent

Related

Display ContextMenu on LongPress for a View in xamarin forms

Hi,
Could you please let me know how to display a context menu on long press effect.I have added a ListView with Effects but the context menu is not popping up after long pressing the listview.
MainPage.xaml
<ContentView x:Name="Parent" BackgroundColor="White" Padding="20" >
<dg:DataGrid ItemsSource="{Binding Data}" SelectionEnabled="True" RowHeight="70" HeaderHeight="50" BorderColor="#CCCCCC" HeaderBackground="#E0E6F8" ActiveRowColor="#8899AA">
<dg:DataGrid.Columns>
<dg:DataGridColumn Title="Logo" PropertyName="Logo" Width="50" SortingEnabled="False">
<dg:DataGridColumn.CellTemplate>
<DataTemplate>
<ListView x:Name="MainListView" local:LongPressedEffect.Command="{Binding ShowAlertCommand}" local:LongPressedEffect.CommandParameter="{Binding .}">
<ListView.Effects>
<local:LongPressedEffect />
</ListView.Effects>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Text="Add" ></MenuItem>
<MenuItem Text="Delete" ></MenuItem>
<MenuItem Text="Edit" ></MenuItem>
</ViewCell.ContextActions>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</dg:DataGridColumn.CellTemplate>
</dg:DataGridColumn>
<dg:DataGridColumn Title="Team" PropertyName="Name" Width="2*" >
</dg:DataGridColumn>
<dg:DataGridColumn Title="Win" PropertyName="Win" Width="2*">
<dg:DataGridColumn.CellTemplate>
<DataTemplate>
<Picker x:Name="Fruits" Title="Fruits" HorizontalOptions="FillAndExpand">
<Picker.Items>
<x:String>Apple</x:String>
<x:String>Orange</x:String>
</Picker.Items>
</Picker>
</DataTemplate>
</dg:DataGridColumn.CellTemplate>
</dg:DataGridColumn>
<dg:DataGridColumn Title="Loose" PropertyName="Loose" Width="1*">
</dg:DataGridColumn>
<dg:DataGridColumn PropertyName="Home">
<dg:DataGridColumn.FormattedTitle>
<FormattedString>
<Span Text="Home" ForegroundColor="Black" FontSize="13" FontAttributes="Bold"/>
<Span Text=" (win-loose)" ForegroundColor="#333333" FontSize="11" />
</FormattedString>
</dg:DataGridColumn.FormattedTitle>
</dg:DataGridColumn>
<dg:DataGridColumn Title="Percentage" PropertyName="Percentage"/>
<dg:DataGridColumn Title="Streak" PropertyName="Streak" Width="0.7*"/>
</dg:DataGrid.Columns>
</ContentView>
LongPressedEffect.cs
public class LongPressedEffect : RoutingEffect
{
public LongPressedEffect() : base("MyApp.LongPressedEffect")
{
}
public static readonly BindableProperty CommandProperty = BindableProperty.CreateAttached("Command", typeof(ICommand), typeof(LongPressedEffect), (object)null);
public static ICommand GetCommand(BindableObject view)
{
return (ICommand)view.GetValue(CommandProperty);
}
public static void SetCommand(BindableObject view, ICommand value)
{
view.SetValue(CommandProperty, value);
}
public static readonly BindableProperty CommandParameterProperty = BindableProperty.CreateAttached("CommandParameter", typeof(object), typeof(LongPressedEffect), (object)null);
public static object GetCommandParameter(BindableObject view)
{
return view.GetValue(CommandParameterProperty);
}
public static void SetCommandParameter(BindableObject view, object value)
{
view.SetValue(CommandParameterProperty, value);
}
}
AndroidLongPressedEffect.cs
public class AndroidLongPressedEffect : PlatformEffect
{
private bool _attached;
/// <summary>
/// Initializer to avoid linking out
/// </summary>
public static void Initialize() { }
/// <summary>
/// Initializes a new instance of the
/// <see cref="T:Yukon.Application.AndroidComponents.Effects.AndroidLongPressedEffect"/> class.
/// Empty constructor required for the odd Xamarin.Forms reflection constructor search
/// </summary>
public AndroidLongPressedEffect()
{
}
/// <summary>
/// Apply the handler
/// </summary>
protected override void OnAttached()
{
//because an effect can be detached immediately after attached (happens in listview), only attach the handler one time.
if (!_attached)
{
if (Control != null)
{
Control.LongClickable = true;
Control.LongClick += Control_LongClick;
}
else
{
Container.LongClickable = true;
Container.LongClick += Control_LongClick;
}
_attached = true;
}
}
/// <summary>
/// Invoke the command if there is one
/// </summary>
/// <param name="sender">Sender.</param>
/// <param name="e">E.</param>
private void Control_LongClick(object sender, Android.Views.View.LongClickEventArgs e)
{
Console.WriteLine("Invoking long click command");
var command = LongPressedEffect.GetCommand(Element);
command?.Execute(LongPressedEffect.GetCommandParameter(Element));
}
/// <summary>
/// Clean the event handler on detach
/// </summary>
protected override void OnDetached()
{
if (_attached)
{
if (Control != null)
{
Control.LongClickable = true;
Control.LongClick -= Control_LongClick;
}
else
{
Container.LongClickable = true;
Container.LongClick -= Control_LongClick;
}
_attached = false;
}
}
}
Any help is very much appreciated!
Please let me know if more information is required.
You can set a property in App.cs as currentPage.
public static ContentPage currentPage;
And set it in the contentPage which contains your listView.
public xxxPage()
{
InitializeComponent();
App.currentPage = this;
}
And in LongPressedEffect.cs
public static ICommand GetCommand(BindableObject view)
{
//do something you want
App.currentPage.DisplayActionSheet("ActionSheet: Send to?", "Cancel", null, "Email", "Twitter", "Facebook");
return (ICommand)view.GetValue(CommandProperty);
}

Caliburn Micro Navigation with MainMenu and SubMenu [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
The first thanks Charleh for caliburn.micro navigation solution.
How to Active SubMenu navigate to Page2 and Deactive if navigate other page?
ShellView.xaml
<Window x:Class="Navigation.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600" WindowStartupLocation="CenterScreen" Width="800" Height="600">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!--Header-->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<ContentControl Grid.Column="1" Grid.Row="0" x:Name="MainMenuRegion" HorizontalContentAlignment="Stretch" HorizontalAlignment="Right" Margin="0,9,17,0" />
<ContentControl Grid.Column="1" Grid.Row="1" x:Name="SubMenuRegion" HorizontalContentAlignment="Stretch" HorizontalAlignment="Right" Margin="0,0,17,0" />
</Grid>
<!--Content-->
<ContentControl Grid.Row="2" x:Name="ActiveItem"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
</ContentControl>
</Grid>
</Window>
ShellViewModel.cs
namespace Navigation
{
public class ShellViewModel : Conductor<object>.Collection.OneActive, IShellViewModel, IHandle<NavigationEventMessage>
{
public ShellViewModel(IEventAggregator eventAggregator, INavigationService navigationService, IPage1ViewModel page1ViewModel, IPage2ViewModel page2ViewModel,IMainMenuViewModel mainMenuViewModel, ISubMenuViewModel subMenuViewModel)
{
_eventAggregator = eventAggregator;
_eventAggregator.Subscribe(this);
navigationService.Navigate(typeof(IPage1ViewModel), null);
_page1ViewModel = page1ViewModel;
_page2ViewModel = page2ViewModel;
Items.Add(_page1ViewModel);
Items.Add(_page2ViewModel);
ActiveItem = _page1ViewModel;
}
private readonly IEventAggregator _eventAggregator;
private readonly IPage1ViewModel _page1ViewModel;
private readonly IPage2ViewModel _paage2ViewModel;
public IMainMenuViewModel MainMenuRegion { get; set; }
public ISubMenuViewModel SubMenuRegion { get; set; }
public void Handle(NavigationEventMessage message)
{
ActivateItem(message.ViewModel);
}
}
}
public interface IShellViewModel
{
}
public interface INavigationService
{
void Navigate(Type viewModelType, object modelParams);
}
public class NavigationEventMessage
{
public IScreen ViewModel { get; private set; }
public NavigationEventMessage(IScreen viewModel)
{
ViewModel = viewModel;
}
}
public class NavigationService : INavigationService
{
// Depends on the aggregator - this is how the shell or any interested VMs will receive
// notifications that the user wants to navigate to someplace else
private IEventAggregator _aggregator;
public NavigationService(IEventAggregator aggregator)
{
_aggregator = aggregator;
}
// And the navigate method goes:
public void Navigate(Type viewModelType, object modelParams)
{
// Resolve the viewmodel type from the container
var viewModel = IoC.GetInstance(viewModelType, null);
// Inject any props by passing through IoC buildup
IoC.BuildUp(viewModel);
// Check if the viewmodel implements IViewModelParams and call accordingly
var interfaces = viewModel.GetType().GetInterfaces()
.Where(x => typeof(IViewModelParams).IsAssignableFrom(x) && x.IsGenericType);
// Loop through interfaces and find one that matches the generic signature based on modelParams...
foreach (var #interface in interfaces)
{
var type = #interface.GetGenericArguments()[0];
var method = #interface.GetMethod("ProcessParameters");
if (type.IsAssignableFrom(modelParams.GetType()))
{
// If we found one, invoke the method to run ProcessParameters(modelParams)
method.Invoke(viewModel, new object[] { modelParams });
}
}
// Publish an aggregator event to let the shell/other VMs know to change their active view
_aggregator.Publish(new NavigationEventMessage(viewModel as IScreen));
}
}
// This is just to help with some reflection stuff
public interface IViewModelParams { }
public interface IViewModelParams<T> : IViewModelParams
{
// It contains a single method which will pass arguments to the viewmodel after the nav service has instantiated it from the container
void ProcessParameters(T modelParams);
}
public class ViewInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
// The 'true' here on the InSameNamespaceAs causes windsor to look in all sub namespaces too
container.Register(Component.For<IShellViewModel>().ImplementedBy<ShellViewModel>().LifestyleSingleton());
container.Register(Component.For<IPage1ViewModel>().ImplementedBy<Page1ViewModel>().LifestyleSingleton());
container.Register(Component.For<IPage2ViewModel>().ImplementedBy<Page2ViewModel>().LifestyleSingleton());
container.Register(Component.For<IMainMenuViewModel>().ImplementedBy<MainMenuViewModel>().LifestyleSingleton());
container.Register(Component.For<ISubMenuViewModel>().ImplementedBy<SubMenuViewModel>().LifestyleSingleton());
}
}
public class NavigationInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<INavigationService>().ImplementedBy<NavigationService>());
}
}
public class CaliburnMicroInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
// Register the window manager
container.Register(Component.For<IWindowManager>().ImplementedBy<WindowManager>());
// Register the event aggregator
container.Register(Component.For<IEventAggregator>().ImplementedBy<EventAggregator>());
}
}
MainMenuView.xaml
<UserControl x:Class="Navigation.Views.MainMenuView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top">
<RadioButton IsChecked="True" Content="Page1" cal:Message.Attach="[Event Checked]=[Action Page1Checked]"/>
<RadioButton Content="Page2" cal:Message.Attach="[Event Checked]=[Action Page2Checked]"/>
</StackPanel>
</Grid>
</UserControl>
MainMenuViewModel.cs
namespace Navigation.ViewModels
{
public class MainMenuViewModel : Conductor<object>.Collection.OneActive, IMainMenuViewModel
{
private readonly IEventAggregator _eventAggregator;
private bool _isAssemblyManagementModule;
public MainMenuViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
public void Page1Checked()
{
NavigationService navigationService = new NavigationService(_eventAggregator);
navigationService.Navigate(typeof(IPage1ViewModel), null);
}
public void Page2Checked()
{
NavigationService navigationService = new NavigationService(_eventAggregator);
navigationService.Navigate(typeof(IPage2ViewModel), null);
}
}
public interface IMainMenuViewModel
{
}
}
SubMenuView.xaml
<UserControl x:Class="Navigation.Views.SubMenuView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top">
<RadioButton IsChecked="True" Content="SubPage1" cal:Message.Attach="[Event Checked]=[Action SubPage1Checked]"/>
<RadioButton Content="SubPage2" cal:Message.Attach="[Event Checked]=[Action SubPage2Checked]"/>
</StackPanel>
</Grid>
</UserControl>
SubMenuViewModel.cs
namespace Navigation.ViewModels
{
public class SubMenuViewModel : Conductor<object>.Collection.OneActive, ISubMenuViewModel
{
private readonly IEventAggregator _eventAggregator;
private bool _isAssemblyManagementModule;
public SubMenuViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
public void SubPage1Checked()
{
NavigationService navigationService = new NavigationService(_eventAggregator);
navigationService.Navigate(typeof(ISubPage1ViewModel), null);
}
public void SubPage2Checked()
{
NavigationService navigationService = new NavigationService(_eventAggregator);
navigationService.Navigate(typeof(ISubPage2ViewModel), null);
}
}
public interface ISubMenuViewModel
{
}
}
Not really an answer to the actual question but more a warning: You have some other issues with the IoC container and how you are using it
You are creating a new navigation service instance for each command in your viewmodels...that's not following the IoC or service methodology.
The navigation service should be resolved by the container so your viewmodel constructor should contain an INavigationService parameter
e.g. your constructor for MainMenuViewModel should look like this:
private INavigationService _navigationService;
public MainMenuViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
}
... and usage:
public void Page1Checked()
{
_navigationService.Navigate(typeof(IPage1ViewModel), null);
}
This is because the container will automatically inject the INavigationService implementation into your VM. You don't need a reference to IEventAggregator implementation (unless your VM is dependent on it, which it doesn't appear to be) and you should not be manually instantiating the NavigationService instance since this is the job of the container
Is this your first time using IoC or MVVM? Can you post some more information (maybe with screenshots) on what you are experiencing and what you expect?
Edit:
Ok this is all I can give you until I know what you are doing with the project you sent me (prism or move to CM?)
Caliburn.Micro uses IConductor<T> as the base for all windows which may conduct/manage an active screen/item. The Conductor<T> is the standard implementation of this interface and is usually used to manage IScreen based concretions.
IConductor interface
http://caliburnmicro.codeplex.com/SourceControl/changeset/view/ae25b519bf1e46a506c85395f04aaffb654c0a08#src/Caliburn.Micro.Silverlight/IConductor.cs
and implementation
http://caliburnmicro.codeplex.com/SourceControl/changeset/view/ae25b519bf1e46a506c85395f04aaffb654c0a08#src/Caliburn.Micro.Silverlight/Conductor.cs
The default conductor manages 1 screen. There are a couple of nested classes which implement multiple screens - Conductor<T>.Collection.OneActive and Conductor<T>.Collection.AllActive allowing either one or all of its items to be active at a time - (e.g. an example of OneActive is the Internet Explorer window with tabs and an example of AllActive is Visual Studio 2010 tool windows)
In order to work with this conductor implementation you should ideally use IScreen (or the concrete Screen class)
IScreen interface
http://caliburnmicro.codeplex.com/SourceControl/changeset/view/ae25b519bf1e46a506c85395f04aaffb654c0a08#src/Caliburn.Micro.Silverlight/IScreen.cs
and implementation
http://caliburnmicro.codeplex.com/SourceControl/changeset/view/ae25b519bf1e46a506c85395f04aaffb654c0a08#src/Caliburn.Micro.Silverlight/Screen.cs
Basically, with these implementations, if the main window is deactivated, it is easy to bubble the 'deactivate' message down to all the children and their children and so on. It also means that a screen gets a notification that it has been activated (OnActivate etc)
e.g.
class ParentWindow : Conductor<IScreen>
{
void DoSomething()
{
ActivateItem(ItemToActivate); // Previous item is automatically deactivated etc
}
override OnActivate()
{
// Activate children or whatever
}
}
class SomeChildWindow : Screen
{
}
It's important to note that Conductor<T> subclasses Screen so it's possible to have child conductors and grandchild conductors that will all obey lifecycle.
I'm not sure if there are Prism equivalents
There is some good Caliburn Micro documentation regarding screens and lifecycle:
http://caliburnmicro.codeplex.com/wikipage?title=Screens%2c%20Conductors%20and%20Composition&referringTitle=Documentation
If you are still using Prism and not Caliburn.Micro and there is no Prism equivalent, then at least the Caliburn.Micro implementations will give you some guidance

ICommand does not fire with button in ItemTemplate

I am currently doing a test with ICommand and I wonder why ICommand does not fire with button in ListBox.ItemTemplate. But when used outside the template, it works.
here's the window xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1" x:Class="WpfApplication1.Window2"
Title="Window2" Height="300" Width="300">
<Window.DataContext>
<local:W2VM/>
</Window.DataContext>
<Grid>
<ListBox x:Name="listHistory" BorderThickness="0" Margin="0" Padding="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding History}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding ''}" />
<Button
Grid.Column="1"
HorizontalAlignment="Right"
x:Uid="btnDeleteHistoryItem"
x:Name="btnDeleteHistoryItem"
Content="r"
FontFamily="Marlett"
Visibility="Hidden" Command="{Binding MeClick}"
/>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Visibility" TargetName="btnDeleteHistoryItem" Value="Visible" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content=" exit " VerticalAlignment="Bottom" Command="{Binding ExitCommand}" />
</Grid>
</Window>
here's the complete ViewModel code
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window2.xaml
/// </summary>
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
}
}
public class W2VM : ViewModelBase
{
public List<string> _History = new List<string>();
public List<string> History
{
get { return this._History; }
}
public ICommand MeClick
{
get;
internal set;
}
public ICommand ExitCommand
{
get;
internal set;
}
public W2VM()
{
this.History.AddRange(new string[] {
"jayson", "hello", "world"
});
this.MeClick = new RelayCommand(Test);
this.ExitCommand = new RelayCommand(Exit);
}
void Exit()
{
Application.Current.Shutdown();
}
void Test()
{
Debug.WriteLine("hello world");
MessageBox.Show("do something incredible");
}
}
}
Test() does not fire
ok I got it working..
<Window.Resources>
<me:W2VM x:Key="local" />
</Window.Resources>
instead of
<Window.DataContext>
<local:W2VM/>
</Window.DataContext>
and my window grid
<Grid DataContext="{StaticResource local}">
<ListBox x:Name="listHistory" BorderThickness="0" Margin="0" Padding="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding History}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding ''}" />
<Button
Grid.Column="1"
HorizontalAlignment="Right"
x:Uid="btnDeleteHistoryItem"
x:Name="btnDeleteHistoryItem"
Content="r"
FontFamily="Marlett"
Visibility="Hidden" Command="{Binding MeClick, Source={StaticResource local}}" />
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Visibility" TargetName="btnDeleteHistoryItem" Value="Visible" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content=" exit " VerticalAlignment="Bottom" Command="{Binding ExitCommand}" />
</Grid>
now this will raise another question.
How would I know which ListViewItem was clicked when the btnDeleteHistoryItem command was just routed?
Are you using the relaycommand of mvvm-light?
I use command parameters to pass information to the command method:
<Button
Grid.Column="1"
HorizontalAlignment="Right"
x:Uid="btnDeleteHistoryItem"
x:Name="btnDeleteHistoryItem"
Content="r"
FontFamily="Marlett"
Visibility="Hidden" Command="{Binding MeClick, Source=StaticResource local}}"
CommandParameter="YourUniqueIdentifyingVariable" />
and then in your view model:
public RelayCommand<string> MeClick{
get { return _MyClick; }
private set { _MyClick = value; }
}
public New()
{
MeClick = new RelayCommand<string>(MySub, MySubIsEnabled);
}
private void MySub(string sParam)
{
//do stuff here, YourUniqueIdentifyingVariable is sParam
}
private bool MySubIsEnabled(string sParam)
{
return true;
}
you can bind "YourUniqueIdentifyingVariable" to the ID of the record or some other value that you can process in your command method
Code is untested but should work

XAML template binding in Windows 8

I am walking through Windows Store Sample Application XAML Twitter Client 1, to get the same features in my own application. But i can't get binding work in 1 to 1 sample page.
This is my grid for displaying friends:
<GridView x:Name="FriendsGrid"
Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="10,10,0,0"
ItemsSource="{Binding Friends}"
ItemTemplate="{StaticResource FriendItemTemplate}"
Grid.ColumnSpan="2">
<GridView.DataContext>
<Model:FriendsViewModel/>
</GridView.DataContext>
Template for binding:
<Page.Resources>
<DataTemplate x:Key="FriendItemTemplate">
<Grid Height="200" Width="300">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image HorizontalAlignment="Left"
Height="80" Width="130"
Margin="10,10,0,0"
VerticalAlignment="Top"
Source="{Binding RealPhoto}"
Stretch="UniformToFill"/>
<TextBlock Grid.Column="1"
HorizontalAlignment="Left"
Margin="10,10,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Height="80"
Width="130"
Text="{Binding FirstName}"/>
<TextBlock HorizontalAlignment="Left"
Margin="10,10,0,0"
Grid.Row="1"
TextWrapping="Wrap"
Text="{Binding LastName}"
VerticalAlignment="Top"
Width="280" Height="80"
Grid.ColumnSpan="2" />
</Grid>
</DataTemplate>
</Page.Resources>
In my code-behind file:
private FriendsViewModel _model;
public MyPage()
{
this.InitializeComponent();
_model = new FriendsViewModel();
FriendsGrid.DataContext = _model;
}
Than i populate model, in application i see exactly the same items count that i`ve added, but items are empty. Using debug i see, that model is not empty.
Also when i am hard-coding values in templates, they are visible.
Test project on GitHub
I forgot to add getters and setters to properties of my model. Initially i had this:
public double Uid;
Than i added {get; set;}
[DataContract]
public class Friend
{
[DataMember(Name = "uid")]
public double Uid { get; set; }
[DataMember(Name="first_name")]
public string FirstName { get; set; }
[DataMember(Name="last_name")]
public string LastName { get; set; }
[DataMember(Name="online")]
public bool Online { get; set; }
[DataMember(Name = "photo")]
public string Photo { get; set; }
public ImageSource RealPhoto { get; set; }
}
To see changes in your view model you need to implement INotifyPropertyChanged. Part of doing this is calling NotifyPropertyChanged on a property if its value changes.

Windows Phone 7 - TextBlock Text binding to ViewModel not returning anythinig

I have built a view model and the listbox binds to the ObervableCollection, but a textbox I am using for a temp url wont bind and return data. I am not getting any errors either on compile or run
ViewModel:
public class HomepageModel:INotifyPropertyChanged
{
public TextBlock bgrImg{get;set;}
public ObservableCollection<MenuItem> menu {get; private set;}
public HomepageModel()
{
this.menu = new ObservableCollection<MenuItem>();
}
public void Load()
{
bgrImg = new TextBlock();
bgrImg.Text = "/Windows7MobileClient;component/Images/Desert.jpg";
//bgrImg = ;
menu.Add(new MenuItem("Feed",""));
menu.Add(new MenuItem("Messages",""));
menu.Add(new MenuItem("Media",""));
menu.Add(new MenuItem("Favourites",""));
menu.Add(new MenuItem("Freinds",""));
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Homepage.xaml
<controls:PanoramaItem Header="menu">
<Grid>
<TextBlock Text="{Binding bgrImg}"/>
<ListBox x:Name="FirstListBox" Margin="0,0,-12,0" ItemsSource="{Binding menu}" MouseLeftButtonUp="FirstListBox_MouseLeftButtonUp" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432">
<TextBlock Text="{Binding label}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</controls:PanoramaItem>
I eventual want to use the string for the panorama background image. Sorry if this seems realy obviously simply.
Chris
You need to call NotifyPropertyChanged() in your setters for the items you wish to bind to.
One more thing I noticed: You are trying to Bind TextBlock to a string Property:
public TextBlock bgrImg{get;set;}
<TextBlock Text="{Binding bgrImg}"/>
Change the type of the property to string:
public string bgrImg{get;set;}
<TextBlock Text="{Binding bgrImg}"/>

Resources