MainWindow.xaml:
<Window x:Class="POGPOS.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:local="clr-namespace:POGPOS.Views"
mc:Ignorable="d"
Loaded="StartApi"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Open Window" Click="ButtonClicked" Height="25" HorizontalAlignment="Left"
Margin="379,264,0,0" Name="button1" VerticalAlignment="Top" Width="100" />
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonClicked(object sender, RoutedEventArgs e)
{
SubWindow subWindow = new SubWindow();
subWindow.Show();
}
}
SubWindow.xaml:
<Window x:Class="POGPOS.Views.Subwindow"
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:POGPOS.Views"
mc:Ignorable="d"
Name="Detail" Height="2400" Width="1765" AllowsTransparency ="True">
<Grid>
<Button Content="Open Window" Click="ButtonClicked" Height="25" HorizontalAlignment="Left"
Margin="379,264,0,0" Name="button1" VerticalAlignment="Top" Width="100" />
</Grid>
</Window>
SubWindow.xaml.cs
public partial class DetailView : Window
{
public DetailView() : base()
{
--------------------------------
}
}
But the error here is : InvalidOperationException: Window must be the root of the tree. Cannot add Window as a child of Visual.
Related
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" );
}
}
I have 2 UserControl, where the Usercontrol should get the Updated Data from MainWindow
<Window x:Class="BindingUserControl.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:BindingUserControl.Pages"
xmlns:local1="clr-namespace:BindingUserControl"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local1:CommonViewModel x:Key="ABC"/>
</Window.Resources>
<Grid>
<local:UserControl1 DataContext="{Binding Source={StaticResource ABC}}" Margin="0,0,520.6,264"/>
<TextBox Width ="100" Height="100" Text="{Binding CommonProperity}"/>
<Button Width="100" Height="100" RenderTransformOrigin="-1.85,1.404" Margin="139,208,554.6,112" Click="Button_Click"></Button>
</Grid>
UserControl
<UserControl x:Class="BindingUserControl.Pages.UserControl1"
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:BindingUserControl"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Local:CommonViewModel x:Key="ABC"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource ABC}}" >
<TextBox Width="100" Height="100" Text="{Binding CommonProperity ,Mode=TwoWay}" />
</Grid>
Viewmodel
namespace BindingUserControl
{
class CommonViewModel: INotifyPropertyChanged
{
private string _Localtextdata;
public string CommonProperity
{
get { return _Localtextdata; }
set
{
_Localtextdata = value;
INotifyPropertyChanged("CommonProperity");
}
}
private void INotifyPropertyChanged(string ProperityName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(ProperityName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
There is no updated text in the usercontrol textbox when ever the Mainwindow textbox get any entry.
Where is my mistake?
You should only create one instance of CommonViewModel and let the UserControl inherit the DataContext from the window. Don't explicitly set the DataContext of the UserControl or any its child elements somewhere:
<Window x:Class="BindingUserControl.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:BindingUserControl.Pages"
xmlns:local1="clr-namespace:BindingUserControl"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<!-- Set the DataContext property -->
<Window.DataContext>
<local1:CommonViewModel x:Key="ABC"/>
</Window.DataContext>
<Grid>
<local:UserControl1 Margin="0,0,520.6,264"/>
<TextBox Width ="100" Height="100" Text="{Binding CommonProperity}"/>
<Button Width="100" Height="100" RenderTransformOrigin="-1.85,1.404" Margin="139,208,554.6,112" Click="Button_Click"></Button>
</Grid>
</Window>
<UserControl x:Class="BindingUserControl.Pages.UserControl1"
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:BindingUserControl"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox Width="100" Height="100" Text="{Binding CommonProperity ,Mode=TwoWay}" />
</Grid>
</UserControl>
I have MainWindow.xaml that has ContentControl.
I have 4 UserControls that i created.
I want to change content of ContentControl in MainWindow.xaml when button pressed inside of my UserControl.
Here is my MainWindow.xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:KIOSK" mc:Ignorable="d" x:Class="KIOSK.MainWindow"
Title="MainWindow" Height="350" Width="525" WindowState="Maximized">
<ContentControl Name="contentMain">
<local:main_screen />
</ContentControl>
</Window>
Here my UserControls:
1)main_screen.xaml
<UserControl x:Class="KIOSK.main_screen"
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 Name="grid1" ShowGridLines="True">
<Button Margin="10" Background="#FFA4F200" Click="Button_Click"/>
</Grid>
</UserControl>
2) ClubRules.xaml
<UserControl x:Class="KIOSK.ClubRules"
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" Background="White">
<Grid ShowGridLines="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="grid1">
<Button Margin="0,15,0,15" Background="#FFFE0555" HorizontalAlignment="Center" Click="Button_Click" />
</Grid>
</UserControl>
Inside of main_creen.xaml.cs i wrote for button pressed:
ClubRules cr = new ClubRules();
MainWindow mw = new MainWindow();
mw.contentMain.Content = new ClubRules();
But its not working..
I want to change Content of ContentControl inside of UserControl when button pressed.
Use delegates and events for your scenario.
Publish an event main_screen.xaml.cs and Subscribe the event in MainWindow.xaml.cs
Publish the event
main_screen.xaml.cs
public partial class main_screen: UserControl
{
public Delegate del;
public main_screen()
{
InitializeComponent();
}
public void method1()
{
del.DynamicInvoke();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
method1();
}
}
Subscribe that event in MainWindow.xaml.cs
MainWindow.Xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:KIOSK" mc:Ignorable="d" x:Class="KIOSK.MainWindow"
Title="MainWindow" Height="350" Width="525" WindowState="Maximized">
<ContentControl Name="contentMain">
<local:main_screen x:Name="main_screen_obj" />
</ContentControl>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public delegate void ValuePassDelegate();
public event ValuePassDelegate ValuePassEvent;
public MainWindow()
{
InitializeComponent();
ValuePassEvent += new ValuePassDelegate(method1);
main_screen_obj.del = ValuePassEvent;
}
public void method1()
{
contentMain.Content = new ClubRules();
}
}
You are creating a new MainWindow() instead of using the one that is being displayed. You should be assigning the ClubRules to the Content of the one that is being displayed.
One way to do that is by bringing the button from the UserControl to the MainWindow itself. Other way as suggested by #decoherence is by using the singleton pattern.
There could be more ways, but you basically need to use the same instance of the MainWindow that has been displayed.
EDIT: It seems like that I needed to change the height of RowDefinition. Thanks goes to Alvaro. However:
how do I reference different elements inside my usercontrol (change their properties), when I want to change them in MainWindow.xaml and MainWindow.xaml.cs?
I have two XAML files in the same namespace.
MainWindow.xaml
List.xaml
When I try to add List.xaml usercontrol to my mainwindow xaml (that is insert xaml from another file), it does not show up.
I insert usercontrol that exists in Lemosystem namespace and inside View folder.
xmlns:lemoview="clr-namespace:Lemosystem.View"
I add usercontrol to my MainWindow.xaml:
<lemoview:List/>
Nothing shows up. Here is my List XAML (code is the default):
<UserControl x:Class="Lemosystem.View.List"
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>
<Label Content="What do you want to do today?" HorizontalAlignment="Left" Margin="10,96,-83,0" VerticalAlignment="Top" Height="44" Width="373" FontSize="24" FontWeight="Bold"/>
</Grid>
</UserControl>
I expect the label from my usercontrol to show up in MainWindow.xaml GUI, but it doesn't.
MainWindow.xaml
<Window x:Class="Lemosystem.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lemocontroller="clr-namespace:Lemosystem.Controller"
xmlns:lemoview="clr-namespace:Lemosystem.View"
Title="{Binding Path=SystemName}" Height="603" Width="827"
ResizeMode="NoResize" WindowStartupLocation="Manual"
>
<Grid Name="Window" Margin="0,0,2,0">
<Grid.RowDefinitions>
<RowDefinition Height="0*"/>
<RowDefinition/>
</Grid.RowDefinitions>
...
<lemoview:List/>
...
</Grid>
</Window>
And how do I reference different elements inside my usercontrol (change their properties), when I want to change them in MainWindow.xaml and MainWindow.xaml.cs?
So, I created a project with :
List.Xaml
<UserControl x:Class="WpfApplication1.List"
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>
<Label Content="{Binding TextToDisplay}"
HorizontalAlignment="Left"
Margin="10,96,-83,0"
VerticalAlignment="Top"
Height="44"
Width="373"
FontSize="24"
FontWeight="Bold" />
</Grid>
</UserControl>
ListViewModel.cs:
public class ListViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private string textToDisplay;
public string TextToDisplay
{
get { return textToDisplay; }
set { textToDisplay = value; OnPropertyChanged("TextToDisplay"); }
}
public ListViewModel(string value)
{
TextToDisplay = value;
}
}
}
MainWindow.Xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:lemoview="clr-namespace:WpfApplication1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Button Content="Click Me" HorizontalAlignment="Center" Click="Button_OnClick"></Button>
<ListView Grid.Row="1" ItemsSource="{Binding MyList}"></ListView>
</Grid>
</Window>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyList=new ObservableCollection<ListViewModel>();
}
private ObservableCollection<ListViewModel> myList;
public ObservableCollection<ListViewModel> MyList
{
get { return myList; }
set { myList = value; }
}
private void Button_OnClick(object sender, RoutedEventArgs e)
{
MyList.Add(new ListViewModel("MyValue"));
}
}
App.xaml:
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<DataTemplate DataType="{x:Type wpfApplication1:ListViewModel}">
<wpfApplication1:List />
</DataTemplate>
</Application.Resources>
in App.xaml, I just defined the binding between List.xaml and ListViewModel.cs
the viewModel of MainWindow is itself.
after every Click on the button, a new ViewModel is created, added to the list with a defined value (you will need to modify this part, to set the value you want).
I hope it will help you ! it works for me.
How do you like to show something, if you put it il a row that has height ="0" ?
change it to :
<Window x:Class="Lemosystem.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lemocontroller="clr-namespace:Lemosystem.Controller"
xmlns:lemoview="clr-namespace:Lemosystem.View"
Title="{Binding Path=SystemName}" Height="603" Width="827"
ResizeMode="NoResize" WindowStartupLocation="Manual"
>
<Grid Name="Window" Margin="0,0,2,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<lemoview:List/>
</Grid>
I have a scrollviewer which contains a webview as content.When I zoom in(zoom factor > 5), a part of content can not be displayed.So Is this a bug?
[screen capture]
https://www.dropbox.com/s/rpqsor36cm6txbo/zoom_problem.xlsx
XAML File
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ScrollViewer x:Name="svMain" HorizontalScrollBarVisibility="Auto" HorizontalScrollMode="Enabled" VerticalScrollBarVisibility="Auto" VerticalScrollMode="Enabled" ZoomMode="Enabled" MinZoomFactor="0.7" MaxZoomFactor="10.0" Background="White" ViewChanged="svMain_ViewChanged" >
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<WebView Name="webview1" Source="http://www.yahoo.co.jp" Height="400" Width="400"
Grid.Column="1"></WebView>
<TextBlock Name="txtZoom" Margin="10,93,710,616" Grid.Column="1"/>
</Grid>
</ScrollViewer>
</Page>
CS File
namespace App1
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void svMain_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
txtZoom.Text = svMain.ZoomFactor.ToString();
}
}
}