I have this window defined in C#:
<Window x:Class="VirginOneAccount.AccountInfo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Account Information" Height="362" Width="614" Loaded="Window_Loaded">
<Window.Resources>
<DataTemplate x:Key="AccountTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=AccountName}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="418*" />
<ColumnDefinition Width="174*" />
</Grid.ColumnDefinitions>
<ComboBox Height="23" HorizontalAlignment="Stretch" Margin="40,16,42,0" Name="AccountsList" VerticalAlignment="Top" Width="Auto" IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}" ItemTemplate="{StaticResource AccountTemplate}" AllowDrop="False" DataContext="{Binding}" IsEnabled="True" SelectionChanged="AccountsList_SelectionChanged" />
<Button Content="Save Changes" Height="23" HorizontalAlignment="Left" Margin="40,0,0,10" Name="saveChanges" VerticalAlignment="Bottom" Width="90" IsEnabled="False" Click="saveChanges_Click" />
</Grid>
Then in the main form, I call Show() on an instance of the window:
AccountInfo Accounts = new AccountInfo();
Accounts.Show();
But all I see is an empty window (not even the right size). Why isn't it opening my window?
I did a simple window and this worked for me. Take it down to just a textbox and see if it works.
public MainWindow()
{
InitializeComponent();
Window1 win1 = new Window1();
win1.Show();
}
The window class name may be different between the xaml definition and the code behind file.
Example
telerik:RadWindow x:Class="MyWindow"
vs
public partial class My_Window : RadWindow
{
public My_Window()
{
InitializeComponent();
}
}
In this case the initializeComponent() call is unrecognized by the compiler
Related
Using WPF .Net Core 3.1 + Prism.
I've implemented TabControl with dynamically added TabItems.
RegionManager works just fine when trying to navigate to region within MainWindow, but it failed when trying to navigate to region whithin the TabPage. Does not work neither from MainWindowViewModel, nor from TabPageViewModel.
Project's repo may be found here: GitHub.
MainWindow.xaml:
<TabControl Margin="10" ItemsSource="{Binding TabPages, UpdateSourceTrigger=PropertyChanged}">
<TabControl.Resources>
<DataTemplate DataType="{x:Type viewmodels:SomeTabPageViewModel}">
<views:SomeTabPage/>
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type interfaces:ITabPage}" x:Name="dt">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Height="40">
<TextBlock Grid.Column="1" Margin="5,10,10,10" Text="{Binding TabName}" TextAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
</Grid>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
SomeTabPage.xaml:
<UserControl x:Class="WpfPrismRegionFailure.Views.SomeTabPage"
xmlns:prism="http://prismlibrary.com/"
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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="Navigate From Inside Of TabPage (not working)" Command="{Binding NavigateFromInsideOfTabPageCommand}" FontSize="16" Background="Orange"/>
<TextBlock Grid.Row="1" Margin="10,20,0,0" Text="The area below contains region 'RegionInsideTabPage', but can't navigate to it." FontSize="16"/>
<Border Grid.Row="2" BorderBrush="Orange" BorderThickness="2" CornerRadius="10" Margin="10">
<ContentControl Margin="10" prism:RegionManager.RegionName="RegionInsideTabPage"/>
</Border>
</Grid>
</UserControl>
SomeTabPageViewModel.cs:
using Prism.Commands;
using Prism.Ioc;
using Prism.Regions;
using System.Windows.Input;
using WpfPrismRegionFailure.Base;
namespace WpfPrismRegionFailure.ViewModels
{
public class SomeTabPageViewModel : TabPageBase
{
public SomeTabPageViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
this.NavigateFromInsideOfTabPageCommand = new DelegateCommand(OnNavigateFromInsideOfTabPage);
}
public SomeTabPageViewModel(IRegionManager regionManager) : base (regionManager)
{
this.NavigateFromInsideOfTabPageCommand = new DelegateCommand(OnNavigateFromInsideOfTabPage);
}
public ICommand NavigateFromInsideOfTabPageCommand { get; }
private void OnNavigateFromInsideOfTabPage()
{
System.Diagnostics.Trace.WriteLine($"SomeTabPageViewModel _regionManager ContainsRegionWithName RegionInsideTabPage: {this._regionManager.Regions.ContainsRegionWithName("RegionInsideTabPage")}");
this._regionManager.RequestNavigate("RegionInsideTabPage", "RegionContent");
}
}
}
Inside of TabPageViewModel regionManager.Regions.ContainsRegionWithName("RegionInsideTabPage") returns 'false' despite of the region is being declared in XAML
<ContentControl Margin="10" prism:RegionManager.RegionName="RegionInsideTabPage"/>
Project's repo may be found here: GitHub.
Someone heeeeeeelp me please
I have a MainWindow.Xaml file. And one usercontrol PatientWindow.Xaml. How to load the patient window in mainwindow in MVVM architecture?
MainWindow.Xaml
<Window x:Class="PatientAdminTool.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:PatientAdminTool.ViewModel"
xmlns:v="clr-namespace:PatientAdminTool.View"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
ResizeMode="CanResizeWithGrip"
WindowStyle="None"
WindowState="Normal"
Title="PatientAdmin Tools"
Height="750"
Width="1400"
AllowsTransparency="True" MouseLeftButtonDown="OnMouseLeftButtonDown" BorderThickness="1" BorderBrush="#555252" >
<WindowChrome.WindowChrome>
<WindowChrome
CaptionHeight="0"
/>
</WindowChrome.WindowChrome>
</Window>
PatientWindow.xaml
Usercontrol window is mentioned in below
<UserControl x:Class="PatientAdminTool.View.PatientWindow"
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:vm="clr-namespace:PatientAdminTool.ViewModel"
xmlns:v="clr-namespace:PatientAdminTool.View"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" >
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" LastChildFill="True" Height="40" Background="#646161" >
<StackPanel DockPanel.Dock="Left" Orientation="Horizontal">
<TextBlock Margin=" 10,5,0,0" HorizontalAlignment="Center" Text="Patients" FontSize="16" TextAlignment="Center" VerticalAlignment="Center" Foreground="#FFFFFF"/>
</StackPanel>
<StackPanel Margin="10,10,0,0" DockPanel.Dock="Right" Background="Transparent" Orientation="Vertical" HorizontalAlignment="Right" VerticalAlignment="Top" Width="50" >
<StackPanel Background="Transparent" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Focusable="False" ToolTip="Close" VerticalAlignment="Center" Background="#646161" BorderThickness="0" BorderBrush="Transparent" Padding="-4" Click="Button_Click" >
<Button.Content>
<Grid Width="45" Height="23">
<TextBlock Foreground="White" Text="r" FontFamily="Marlett" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</Button.Content>
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}"/>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
</StackPanel>
</DockPanel>
</Grid>
</UserControl>
So I need to load the patient window above of main window using MVVM. Here I need to write load event in corresponding View Model. Please help me to do this.
Just add a ControlPresenter at MainWindow.
<ContentPresenter Content="{Binding YouTypeHere}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type fristViewModel1Type}">
<youControlForViewModel1 />
</DataTemplate>
<DataTemplate DataType="{x:Type secondViewModel2Type}">
<youControlForViewModel2 />
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
And you could change Views via binding different VM to ContentPresenter.
So you want to open a new child window using MVVM? I assume you would open it from MainWindowViewModel.
Solution 1: without strict MVVM
Sometimes its fine to open it directly from the ViewModel:
private void OnOpenPatientWindowCommandExecute()
{
var o = new PatientWindow();
o.ShowDialog();
}
For this you would have to change PatientWindow from UserControl to a Window.
Solution 2: strict MVVM
The solutions following strict MVVM are a little more complex. In the solution I write here you would have to use a Service, add it to your MainWindowViewModel and bind a control from the view to a Command in the ViewModel. Also, its written as if you are using Dependency Injection, that's why you see the service injected in the constructor. You can avoid this by just instantiating the service in the constructor.
MainWindowViewModel.cs
using Prism.Wpf.Commands; // For easy commands
using PatientAdminTool.Services; // Where you put your new service
public class MainWindowViewModel
{
private IShowDialogService _ShowDialogService;
public MainWindowViewModel(IShowDialogService showDialogService)
{
_ShowDialogService = showDialogService;
// Or do: _ShowDialogService = new ShowDialogService();
// But that's not a good practice and won't let you test
// this ViewModel properly.
OpenPatientWindowCommand = new DelegateCommand(OnOpenPatientWindowCommandExecute);
}
public ICommand OpenPatientWindowCommand { get; private set; }
private void OnOpenPatientWindowCommandExecute()
{
_ShowDialogService.ShowPatientWindow();
}
}
Services\IShowDialogService.cs
public interface IShowDialogService
{
void ShowPatientWindow();
void ShowOtherWindow();
// ...
}
Services\ShowDialogService.cs
public class ShowDialogService : IShowDialogService
{
public void ShowPatientWindow()
{
var patientWindowViewModel = new PatientWindowViewModel();
var patientWindow = new PatientWindow();
patientWindow.DataContext = patientWindowViewModel;
patientWindow.ShowDialog();
}
public void ShowOtherWindow()
{
// Other window ...
}
}
Finally, you make the connection in the View like this:
MainWindow.xaml
<Window
xmlns:vm="clr-namespace:PatientAdminTool.ViewModel">
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Button Command="{Binding OpenPatientCommand}">Open Patient</Button>
</Grid>
</Window>
Haven't tried it in Visual Studio yet but that's the idea.
If it's the only thing you are going to be displaying in the same window, just put your view in there like any other control:
<Window x:Class="PatientAdminTool.MainWindow"
xmlns:v="clr-namespace:PatientAdminTool.View"... >
<WindowChrome.WindowChrome>
<WindowChrome
CaptionHeight="0"/>
</WindowChrome.WindowChrome>
<v:PatientWindow/>
</Window>
Do you have a root ViewModel for your window? If so, you can bind to a PatientViewModel:
<v:PatientWindow DataContext="{Binding PatientViewModel}"/>
If not, it's common to set the first DataContext to a ViewModel in the code-behind like this:
<v:PatientWindow Name="PatientWindowView"/>
and:
public partial class Window
{
public MainWindow()
{
InitializeComponent();
PatientWindowView.DataContext = new PatientWindowViewModel();
}
}
If you want to display more than one View, use a ContentPresenter like Shakra has answered.
If you want to open a new window, use what Alberto Cardona López has suggested.
There is much of code. But problem is there:
I've got a Listbox with Control as DataTemplate:
<ListBox x:Name="UpcomingConcertsList" ItemsSource="{Binding UpcomingConcerts}" HorizontalAlignment="Left" Height="350" Margin="10,208,0,0" VerticalAlignment="Top" Width="370">
<ListBox.ItemTemplate>
<DataTemplate>
<Control MouseDoubleClick="UpcomingConcert_DoubleClick">
<Control.Template>
<ControlTemplate>
<Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue" CornerRadius="4" Width="320">
<Grid Margin="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2" Width="100" Height="75" Margin="6" Source="{Binding ImageURL}"/>
<StackPanel Grid.Column="1" Margin="2,6">
<TextBlock FontWeight="Bold" Text="{Binding Name}"/>
<TextBlock Text="{Binding Date, StringFormat={}{0:g}}"/>
<TextBlock Text="{Binding Bands, Converter={StaticResource BandsConverter}}"/>
</StackPanel>
</Grid>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And click event code behind:
private void Concert_DoubleClick(object sender, MouseButtonEventArgs e)
{
Control control = sender as Control;
Concert concert = control.DataContext as Concert;
ConcertView wndw = new ConcertView(concert.ConcertID);
wndw.Show();
}
And ConcertView window is opened but just under my MainWindow. wndw.Activate(), wndw.Focus() don't help.
I tried to do this.IsEnabled = false and wndw.Show() after this. Then my ConcertView was above MainWindow. But as this.IsEnabled comes to true, ConcertView suddenly goes under.
Is ther eany ideas?
But TopMost makes my window being over all the applications What do you mean by this? You're currently using an application and when you click a button, a new window is loaded. So you want the new window to be at topmost itself right?
You can set the Owner property of a window to set it's owner. ie the MainWindow. If you set this then the current window will be owner window.
Window ownedWindow = new Window();
ownedWindow.Owner = this;
ownedWindow.Show();
Now try setting the wndw.TopMost = true;and check if its working.
I'm very new to WPF application development.
I'm writing a simple WPF application in which I'll just have one window and pages will change on click buttons provided in UI.
Here how can have base page in which i'll add some header which is common for all pages i'm designing.
Is there anything like by extending that BasePage, all controls will come to this page?
For example, My app title should come in all page which I don't want to add in XAMLs of all pages.
Please let me know if my assumption itself is wrong.
Edited:
My BasePage:
public class BasePage : Page
{
public BasePage()
{
}
}
XAML of my HomePage:
<local:BasePage x:Class="CCS.ui.HomePage"
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:My.ui"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="HomePage">
<StackPanel>
<WrapPanel Name="root"></WrapPanel>
<Button Name="Home" Content="Home"></Button>
<Button Name="Home3" Content="Home2"></Button>
</StackPanel>
Here I'm not sure where to write controls of header which should be added to BasePage. Because if BasePage is created from XAML It is showing error like "Cannot use Pages generated from XAML".
There are several ways to do what you want. Here I put a small example:
I created a Window with 3 main controls, Menu (for navigation), TextBox (Header) and a Grid (Host)
When I click on the menu, I add a UserControl in the HostGrid.
MainWindow.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Menu>
<MenuItem Header="Home" x:Name="Home" Click="MenuItem_Click"/>
<MenuItem Header="Page 1" x:Name="Page1" Click="MenuItem_Click"/>
<MenuItem Header="Page 2" x:Name="Page2" Click="MenuItem_Click"/>
</Menu>
<TextBlock Grid.Row="1" Text=" Header" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24" Height="40"/>
<Grid Grid.Row="2" x:Name="HostGrid"></Grid>
</Grid>
MainWindow.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
HostGrid.Children.Clear();
switch(((MenuItem)e.OriginalSource).Name)
{
case "Home":
HostGrid.Children.Add(new UserControlHome());
break;
case "Page1":
HostGrid.Children.Add(new UserControl1());
break;
case "Page2":
HostGrid.Children.Add(new UserControl2());
break;
}
}
}
UserControlHome.xaml
<Grid Background="Crimson">
<TextBlock Text="Home" FontSize="18" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
UserControl1.xaml
<Grid Background="Lavender">
<TextBlock Text="Page 1" FontSize="18" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
UserControl2.xaml
<Grid Background="Ivory">
<TextBlock Text="Page 2" FontSize="18" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
I have the following XAML where I have two combobox controls with the same ItemsScource. I used the IsSynchronizedWithCurrentItem=False to attempt to get them to act individually. But still changing one changes the other.
XAML
<Page x:Class="HaMmeR.FantasyFootball.TradeEvalPage"
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"
Title="TradeEvalPage">
<Grid x:Name="masterPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" Grid.Column="0" Style="{DynamicResource dockLsLabel}">
<Label x:Name="teamName1Lbl" Content="Team Name" Style="{DynamicResource lsLabel}" />
<!--IsSynchronizedWithCurrentItem=False Treat datasource as individual-->
<ComboBox x:Name="teamName1Cmb" Margin="2" DockPanel.Dock="Right"
ItemsSource="{Binding Path=FantasyTeams}"
IsSynchronizedWithCurrentItem="False"
DisplayMemberPath="TeamName"
SelectionChanged="teamName1Cmb_SelectionChanged"
SelectedValuePath="TeamName" SelectedValue="{Binding Path=TeamName}"/>
</DockPanel>
<DockPanel Grid.Row="0" Grid.Column="1" Style="{DynamicResource dockLsLabel}">
<Label x:Name="teamName2Lbl" Content="Team Name" Style="{DynamicResource lsLabel}" />
<ComboBox x:Name="teamName2Cmb" Margin="2" DockPanel.Dock="Right"
ItemsSource="{Binding Path=FantasyTeams}"
IsSynchronizedWithCurrentItem="False"
DisplayMemberPath="TeamName"
SelectionChanged="teamName2Cmb_SelectionChanged"
SelectedValuePath="TeamName" SelectedValue="{Binding Path=TeamName}"/>
</DockPanel>
</Grid>
</Page>
.cs File
public partial class TradeEvalPage : Page
{
private FantasyLeague league;
public TradeEvalPage(FantasyLeague League)
{
InitializeComponent();
league = League;
//FantasyTeamCollection team1Source = new FantasyTeamCollection(league.FantasyTeams.ToList<FantasyTeam>());
//FantasyTeamCollection team2Source = new FantasyTeamCollection(league.FantasyTeams.ToList<FantasyTeam>());
//teamName1Cmb.DataContext = team1Source;
//teamName2Cmb.DataContext = team2Source;
masterPanel.DataContext = league;
//mainContent.Text = string.Format("You clicked Trade Evalution of {0}", league.LeagueName);
}
}
I can't figure out what I'm doing wrong. Any help would be appreciated.
I think because you Bind the selectedValue to the TeamName.
SelectedValue="{Binding Path=TeamName}"
If you remove the bind, they probably work. I think whats happen here is, when you change the selection in one combobox, the value of the new selected item is written in the current items-name. So it looks that the first combobox does the same, but if you open it, you'll see that value twice.