I'm having some trouble gaining a working understanding of how Region Navigation works in Prism. I'm trying to create an MVVM based app that loads a main window, and displays a view generated by a login form. After the login form is submitted, I then want to navigate to a new UserControl. I'd like to know if this is also possible without using modules, however for the current implementation, it's modular.
With this current code, the menu bar with a button displays, but not the Login view.
Main Module
App.xaml.cs
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<LoginModule.ModuleLoginModule>();
}
MainWindow.xaml:
<Window x:Class="PrismMVVM.Views.MainWindow"
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:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:local="clr-namespace:PrismMVVM"
mc:Ignorable="d"
Title="PrismMVVM" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0">
<Button Content="Code is Poetry" HorizontalAlignment="Left" Width="Auto"/>
</DockPanel>
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion">
</ContentControl>
</Grid>
</Window>
MainWindowViewModel.cs
namespace PrismMVVM.ViewModels
{
class MainWindowViewModel : BindableBase
{
public IRegionManager _regionManager;
public MainWindowViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
regionManager.RequestNavigate("LoginRegion", "Login");
}
}
}
Login Module
ModuleLoginModule.cs:
namespace LoginModule
{
public class ModuleLoginModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("LoginRegion", typeof(Login));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<Login>();
}
}
}
Login.xaml:
<UserControl x:Class="LoginModule.Views.Login"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:LoginModule.Views"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="White" prism:RegionManager.RegionName="LoginRegion">
<StackPanel Panel.ZIndex="1" Margin="150">
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center">Text</TextBox>
<PasswordBox HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button Background="LightBlue" Content="Login" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
<Rectangle Panel.ZIndex="0" HorizontalAlignment="Center" VerticalAlignment="Center" Fill="LightGray" Height="300" Width="400" />
</Grid>
</UserControl>
I'd like to know if this is also possible without using modules
For sure it is. Modules are completely optional, you can do all the registrations from the bootstrapper / PrismApplication, if you like.
There's nothing wrong with something like this:
public class MyApplication : PrismApplication
{
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<Login>();
}
}
internal class MainWindowViewModel
{
public MainWindowViewModel( IRegionManager regionManager )
{
regionManager.RequestNavigate( "ContentRegion", "Login" );
}
}
Related
In my project I use Prism for the Views and ViewModels. I now want to load another view into a UserControl in the MainWindowView. I read I can do this with this:
_regionManager.RegisterViewWithRegion("MainRegion", typeof(View));
But unfortunately I have no idea how to get to the instance of IRegionManger in my ViewModel. In all examples I found, other variables are used, but it is not shown where they come from.
This is my View:
<Window x:Class="PortfolioVisualizer.MainWindow"
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:local="clr-namespace:PortfolioVisualizer"
mc:Ignorable="d"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="15*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<Button Command="{Binding NavigateCommand}" CommandParameter="AddAssetView">
<StackPanel>
<Image/>
<Label Content="Add Asset"/>
</StackPanel>
</Button>
<Button Command="{Binding NavigateCommand}" CommandParameter="ConfigView">
<StackPanel>
<Image/>
<Label Content="Settings"/>
</StackPanel>
</Button>
</StackPanel>
<Grid Grid.Column="1">
<ContentControl prism:RegionManager.RegionName="MainRegion"/>
</Grid>
</Grid>
</Window>
This is my ViewModel:
public class MainWindowViewModel : ViewModelBase
{
private readonly IRegionManager _RegionManager;
public DelegateCommand<string> NavigateCommand;
public MainWindowViewModel(IRegionManager regionManager)
{
_RegionManager = regionManager;
NavigateCommand = new DelegateCommand<string>(ExecuteNavigateCommand);
_RegionManager.RegisterViewWithRegion("MainRegion", typeof(DashboardView));
}
private void ExecuteNavigateCommand(string viewName)
{
if (string.IsNullOrWhiteSpace(viewName))
return;
_RegionManager.RequestNavigate("ContentRegion", viewName);
}
}
This is the ViewModdelBase
public class ViewModelBase : BindableBase
{
public ViewModelBase()
{
}
}
(I know that the ViewModelBase is just superfluous, but there is something to come later)
You have the container inject the region manager like any other dependency:
internal class MyViewModel
{
public MyViewModel( IRegionManager regionManager )
{
regionManager.DoSomeStuff(); // or just put it into a field for later use
}
}
Note that this only works automatically, if you don't manually new the view model either in code or in xaml. Instead, create it with a factory that is itself injected (e.g. Func<MyViewModel> myViewModelFactory) if you go view model-first (recommended most of the time), or use Prism's ViewModelLocator to have it created as data context if you go view-first.
I am trying to make an app using using MVVMLight that has a sidebar with buttons, each button shows a new usercontrol hosted in a ContentControl. When the user clicks the buttons in the sidebar (Show View1 / Show View2) it shows the views correctly.
My problems arise when the user has already shown a View (it could be View1 or View2 ), say View1 and click (Show View1) ** again ** View1 controls remain with the same values and I would like to show the same view with all controls as if it had restarted. (I know that I could reset all controls within the user control (View1) but my application requires having a new instance of the view every time the button is clicked).
Somehow, in the same scenario when the user is in View 1, switch to view 2 and return to view 1, a new instance is created and shown as I would like. I would like to get the same result without the need to switch to view 2 and return.
Here is a minimal reproducible example of the issue:
ViewModelLocator.cs
using CommonServiceLocator;
using GalaSoft.MvvmLight.Ioc;
namespace SidebarApp.ViewModel
{
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
// Register viewmodels
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<View1ViewModel>();
SimpleIoc.Default.Register<View2ViewModel>();
}
public MainViewModel Main { get { return ServiceLocator.Current.GetInstance<MainViewModel>(); } }
public View1ViewModel View1Vm { get { return ServiceLocator.Current.GetInstance<View1ViewModel>(); } }
public View2ViewModel View2Vm { get { return ServiceLocator.Current.GetInstance<View2ViewModel>(); } }
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
}
MainViewModel.cs
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Windows.Input;
namespace SidebarApp.ViewModel
{
public class MainViewModel : ViewModelBase
{
// Commands
public ICommand ShowView1Command { get; private set; }
public ICommand ShowView2Command { get; private set; }
/// <summary>
/// Property that will cointain the current viewmodel to show
/// ViewModelBase inplements ObservableObject class which imlements INotifyPropertyChanged
/// </summary>
public ViewModelBase CurrentViewModel { get; set; }
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
this.ShowView1Command = new RelayCommand(ShowView1);
this.ShowView2Command = new RelayCommand(ShowView2);
}
private void ShowView1()
{
// I tried this but it doesn't work
//CurrentViewModel = null or View2ViewModel;
CurrentViewModel = new View1ViewModel();
}
private void ShowView2()
{
CurrentViewModel = new View2ViewModel();
}
}
}
MainWindow.xaml
<Window x:Class="SidebarApp.MainWindow"
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:local="clr-namespace:SidebarApp"
mc:Ignorable="d"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Title="MainWindow" Height="348.965" Width="560.683">
<Window.Resources>
<DataTemplate DataType="{x:Type local:View1ViewModel}">
<local:View1View />
</DataTemplate>
<DataTemplate DataType="{x:Type local:View2ViewModel}">
<local:View2View />
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<Button Command="{Binding ShowView1Command}">Show View1</Button>
<Button Command="{Binding ShowView2Command}">Show View2</Button>
</StackPanel>
<ContentControl Grid.Column="1" Content="{Binding Path=CurrentViewModel}"></ContentControl>
</Grid>
</Window>
View1View.xaml
<UserControl x:Class="SidebarApp.View1View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SidebarApp"
mc:Ignorable="d"
DataContext="{Binding View1Vm, Source={StaticResource Locator}}"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="LightPink">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock HorizontalAlignment="Center" Text="Welcome to View 1" FontSize="20"/>
<TextBox HorizontalAlignment="Stretch" Text="Original text value"/>
<CheckBox Content="Some boolean value"/>
</StackPanel>
</Grid>
</UserControl>
View1ViewModel.cs
using GalaSoft.MvvmLight;
namespace SidebarApp
{
public class View1ViewModel : ViewModelBase
{
public View1ViewModel()
{
}
}
}
View2View.xaml
<UserControl x:Class="SidebarApp.View2View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SidebarApp"
mc:Ignorable="d"
DataContext="{Binding View2Vm, Source={StaticResource Locator}}"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="LightCyan">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock HorizontalAlignment="Center" Text="Welcome to View 2" FontSize="20"/>
<TextBox HorizontalAlignment="Stretch" Text="Some text in view2"/>
<Button Content="Button"/>
</StackPanel>
</Grid>
</UserControl>
View2ViewModel.cs
using GalaSoft.MvvmLight;
namespace SidebarApp
{
public class View2ViewModel : ViewModelBase
{
public View2ViewModel()
{
}
}
}
App.xaml
<Application x:Class="SidebarApp.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:SidebarApp" StartupUri="MainWindow.xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d" xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:SidebarApp.ViewModel" />
</ResourceDictionary>
</Application.Resources>
</Application>
For example I enter to the view1 and change the value of the textbox ("Original text value") to another value and I click again in Show View1 the text and everything in the usercontrol stays the same but when I switch to view2 and go back to view1 a new usercontrol is shown with his original values.
This might feel like something of a workaround, but it works. Hopefully it will prove useful. (Obviously make same changes to View2View view/view model).
ViewModelLocator.cs
public View1ViewModel View1Vm { get { return new View1ViewModel(); } }
MainViewViewModel.cs
private void ShowView1()
{
CurrentViewModel = new ViewModelLocator().View1Vm;
}
View1View.xaml
<UserControl x:Class="SidebarApp.View1View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SidebarApp"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="LightPink">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock HorizontalAlignment="Center" Text="Welcome to View 1" FontSize="20"/>
<TextBox HorizontalAlignment="Stretch" Text="{Binding Path=View1Text, Mode=TwoWay}"/>
<CheckBox Content="Some boolean value" IsChecked="{Binding Path=CheckBoxChecked, Mode=TwoWay}"/>
</StackPanel>
</Grid>
</UserControl>
View1ViewModel.cs
public class View1ViewModel : ViewModelBase
{
private string _view1Text;
private bool _checkBoxedChecked;
public string View1Text
{
get
{
return _view1Text;
}
set
{
_view1Text = value;
RaisePropertyChanged("View1Text");
}
}
public bool CheckBoxChecked
{
get
{
return _checkBoxedChecked;
}
set
{
_checkBoxedChecked = value;
RaisePropertyChanged("CheckBoxChecked");
}
}
public View1ViewModel()
{
View1Text = "Original text value";
}
}
I would like to make a page that contains two sub-pages of options.
The problem I've encountered is that I can't access the objects from sub-pages of the main page. I should note that I use only DataContext to script behind.
And here is some of the code that will help you understand better what I mean:
StartPage.xaml
<Page x:Class="WpfApp.StartPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="startPage">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<StackPanel>
<Button Content="Page 1" Command="{Binding FirstPageCommand}"/>
<Button Content="Page 2" Command="{Binding SecondPageCommand}"/>
</StackPanel>
<Frame x:Name="frame" Grid.Column="1" NavigationUIVisibility="Hidden"
Source="Page1.xaml"/>
<StackPanel Grid.Column="1" Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Content="Reset" Margin="10" Command="{Binding ResetCommand}"/>
<Button Content="Save" Margin="10" Command="{Binding SaveCommand}"/>
</StackPanel>
</Grid>
StartPage.xaml.cs
using System.Windows.Controls;
namespace WpfApp
{
/// <summary>
/// Interaction logic for StartPage.xaml
/// </summary>
public partial class StartPage : Page
{
public StartPage()
{
InitializeComponent();
DataContext = new StartPage_DataContext(this);
}
}
}
StartPage_DataContext.cs
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApp
{
public class StartPage_DataContext
{
private Page _Page;
public StartPage_DataContext(Page page)
{
_Page = page;
FirstPageCommand = new RelayCommand(() => FirstPage());
SecondPageCommand = new RelayCommand(() => SecondPage());
SaveCommand = new RelayCommand(() => Save());
ResetCommand = new RelayCommand(() => Reset());
}
private void FirstPage()
{
(_Page as StartPage).frame.NavigationService.Navigate(new Page1());
}
private void SecondPage()
{
(_Page as StartPage).frame.NavigationService.Navigate(new Page2());
}
private void Save()
{
//Here is where I need code for saving both "Page1" and "Page2" elements to Settings class.
//Exeple : Settings._firstCB = Page1.firstCB.IsCheked.Value;
// Settings._secondCB = Page2.firstCB.IsCheked.Value;
}
private void Reset()
{
//Here is where I need code for setting both "Page1" and "Page2" elements to some default values.
//Exemple : Page1.firstCB.IsCheked.Value = false;
// Page2.firstCB.IsCheked.Value = true;
}
public ICommand FirstPageCommand { get; private set; }
public ICommand SecondPageCommand { get; private set; }
public ICommand SaveCommand { get; private set; }
public ICommand ResetCommand { get; private set; }
}
}
Page1.xaml (page2 is similar the only difference is the naming of elements convention)
<Page x:Class="WpfApp.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page1">
<Grid Background="White">
<StackPanel>
<CheckBox x:Name="firstCB" Content="First Combo Box"/>
<CheckBox x:Name="secondCB" Content="Second Combo Box"/>
<ComboBox x:Name="firstCombo">
<ComboBoxItem Content="First Item"/>
<ComboBoxItem Content="Second Item"/>
</ComboBox>
</StackPanel>
</Grid>
Not sure if you have view models for your sub pages,
If you do have, one way of accessing properties of those viewmodel for your check box would be as shown below.
var tt = (((_Page as StartPage).frame.NavigationService.Content as Page1).DataContext as Page1ViewModel).IsCBChecked;
I've tried to adding a Xaml UserControl and/or UserPage in WIndows Desktop project added in Xamarin. None of Windows UI items (page or usercontrol and buttons) are displayed by page renderer. Can you please help where could I be making mistake.
CameraPageRenderer
[assembly: ExportRenderer(typeof(Shared.CameraPage), typeof(CameraPageRenderer))]
namespace MyApp.Windows
{
public class CameraPageRenderer : PageRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
//1st test
this.Children.Add(new PhotoCaptureControl());
//[OR] 2nd Test
this.Children.Add(new PhotoCapturePage());
}
catch (Exception ex)
{
//Logger class
}
}
}
CameraPage
Invoked from Portable library page
public class CameraPage : ContentPage
{
public CameraPage(TaskCompletionSource<MediaFile> SelectionTask)
{
Content = new StackLayout
{
};
}
}
PhotoCaptureControl.xaml
.cs file has Initialize method.
<UserControl x:Class="MyApp.Windows.PhotoCaptureControl"
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:local="using:MyApp.Windows"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<StackPanel>
<TextBlock Text="Capture Photo text" />
<Button x:Name="BtnCapturePhoto"
HorizontalAlignment="Center"
Content="Capture Photo" />
</StackPanel>
</UserControl>
PhotoCapturePage.xaml .cs contains InitializeComponents() method
<Page x:Class="eWorker.Windows.PhotoCapturePage"
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:local="using:eWorker.Windows"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button x:Name="BtnCapturePhoto"
Grid.Row="1"
HorizontalAlignment="Center"
Content="Capture Photo" />
</Grid>
</Page>
I found a partial solution to my problem. It will work in case of PhotoCapturePage but may not in case of UserControl PhotoCaptureControl.
I replaced following line of code
this.Children.Add(new PhotoCapturePage());
with -
this.SetNativeControl(new PhotoCapturePage());
This solution will not work if it is required to add one or more native UserControl.
I am using Caliburn Micro with WPF. I want to create an application with a menu on the left side, and a grid on the right side of the application. When clicking on a menu item, the grid on the right side, will change to another view. The another view will be in a separate file.
MainWindowView:
<UserControl x:Class="CMDemo.Views.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90*" />
<ColumnDefinition Width="210*" />
</Grid.ColumnDefinitions>
<StackPanel Name="LeftMenu">
<Button Name="ChangeDisplay" Content="Click Me"></Button>
<TextBlock x:Name="MyString"></TextBlock>
</StackPanel>
<Grid Grid.Column="1" x:Name="MainGridContent" />
</Grid>
MainWindowViewModel:
public class MainWindowViewModel : PropertyChangedBase
{
private UserControl mainGridContent;
private string myString;
public UserControl MainGridContent
{
get { return this.mainGridContent; }
set
{
this.mainGridContent = value;
NotifyOfPropertyChange(() => this.MainGridContent);
}
}
public string MyString
{
get { return this.myString; }
set
{
this.myString = value;
NotifyOfPropertyChange(() => this.MyString);
}
}
public void ChangeDisplay()
{
this.MainGridContent = new ChangeDisplayView();
this.MyString = "Testing....";
}
}
The changeDisplayViewModel:
public class changeDisplayViewModel: PropertyChangedBase
{
}
The changeDisplayView:
<UserControl x:Class="CMDemo.Views.changeDisplayView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBox content="Hello Caliburn Micro">
</Grid>
When I click the "Click Me" button the TextBlock "MyString" is updated and showing, but the usercontrol is not. What am I doing wrong?
Try changing MainGridContent to a changeDisplayViewModel rather than the view itself.