I have simple WPF app, main window, and button, that on click creates a new modal child
window via my window manager:
class WindowManager : IWindowManager
{
public void AddNewViewWindow()
{
var someWindow = new AddNewView();
someWindow.ShowInTaskbar = false;
someWindow.Owner = Application.Current.MainWindow;
someWindow.ShowDialog();
}
}
MainWindow:
<Window x:Class="LogView.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525">
<StackPanel>
<StackPanel Orientation="Horizontal">
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
<Button Name="AddNewControl" Content="Add New Control" Command="{Binding AddNewViewCommand}" Margin="10">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<CheckBox Name="EditMode" Content="Edit mode" IsChecked="{Binding EditModeEnabled}" Margin="10"/>
</StackPanel>
</StackPanel>
</Window>
ModalChildWindow:
<Window x:Class="LogView.Views.AddNewView"
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:LogView.Views"
xmlns:prism ="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Title="AddNewView" Height="450" Width="800">
<StackPanel>
<TreeView ItemsSource="{Binding DeviceSets}" >
<TreeView.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding Name}" ItemsSource="{Binding Registers}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Name}">
</TextBox>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</Window>
I am also using Prism, my bootstrapper:
class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void InitializeShell()
{
Application.Current.MainWindow.Show();
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
RegisterTypeIfMissing(typeof(IWindowManager), typeof(WindowManager), true);
}
protected override void ConfigureModuleCatalog()
{
var moduleCatalog = (ModuleCatalog)ModuleCatalog;
moduleCatalog.AddModule(typeof(WebSocketClientModule));
}
}
Now, I am experiencing this strange behavior:
When I click the button, modal child window shows up. Everything is fine, I can't click on parent(MainWindow) window. Then, if I minimalize this child modal window, and then bring it back on, the child window stops being modal. I can click on MainWindow and create a second modal window ( the first one is still visible). What is even weird, the second modal window is truly modal, when I minimalize it, bring it on I cannot click on the parent window. If I close the second modal window, I can create it again.
Greetings
Related
I want to develop a desktop application based on WPF. How do I navigate through C # code from one window to another in a window? in the other word, I have tried to set up a click event for a radiobutton that opens another window in frame or border.
<Window x:Class="WpfNavigation2.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:WpfNavigation2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" Closing="Window_Closing">
<Grid>
<Border Margin="10,100,10,10" Background="AliceBlue">
<Grid Name="contergrid">
</Grid>
</Border>
<RadioButton x:Name="radioButton" Content="RadioButton1" HorizontalAlignment="Left" Margin="60,0,0,0" VerticalAlignment="Top" Click="btn1"/>
<RadioButton x:Name="radioButton1" Content="RadioButton2" HorizontalAlignment="Left" Margin="60,37,0,0" VerticalAlignment="Top" Click="btn2"/>
<RadioButton x:Name="radioButton2" Content="RadioButton3" HorizontalAlignment="Left" Margin="60,68,0,0" VerticalAlignment="Top" Click="btn3"/>
</Grid>
</Window>
private void btn1(object sender, RoutedEventArgs e)
{
//open window 1 in border
}
What you are looking for is a ContentPresenter. You can put all kinds of content in a ContentPresenter for example a control
<Border Margin="10,100,10,10" Background="AliceBlue">
<ContentPresenter Name="contentFrame">
</ContentPresenter>
</Border>
private void btn1(object sender, RoutedEventArgs e)
{
Grid grd = new Grid();
grd.Background = new SolidColorBrush(Colors.HotPink);
contentFrame.Content = grd; // replace me with your control / page / window1
}
I am working on a WPF project. I need to display an image when the new window opens, but I don't seem to get it to work. I feel like I've tried everything.
<Window x:Class="iTool.ProfileWindow"
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:iTool"
mc:Ignorable="d"
Title="iTool: User Profile" Height="800" Width="1200" ResizeMode="NoResize">
<Grid>
<StackPanel>
<Label Content="User Profile" FontSize="30" HorizontalContentAlignment="Center"/>
<StackPanel Orientation="Horizontal">
<StackPanel Width="300" Height="700">
<Image x:Name="imgUserProfile" Height="200" Width="200" Margin="50"/>
<TextBlock x:Name="txbFirstName"/>
<TextBlock x:Name="txbLastName"/>
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
</Window>
public partial class ProfileWindow : Window
{
public ProfileWindow()
{
InitializeComponent();
imgUserProfile.Source = new BitmapImage(new Uri(MainWindow.activeUserImage, UriKind.RelativeOrAbsolute));
}
}
In Debug watch:
activeUserImage = "images/samson_profile.jpg"
imgUserProfile.Source = {pack://application:,,,/iTool;component/images/samson_profile.jpg}
The image exists in the "images" folder, but is not added to the project as existing file.
When the ProfileWindow opens all I can see is User Profile label, no image.
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.
I have gridview with custom usercontrols.
Here's the XAML of the usercontrol:
<UserControl
x:Class="App11.VideoPreview"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App11"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="250"
d:DesignWidth="250">
<Grid>
<Button Height="250" Width="250" Padding="0" BorderThickness="0">
<StackPanel>
<Image Name="image1" Height="250" Width="250" Stretch="None"/>
<Grid Margin="0,-74,0,0">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" Opacity="0.5">
<GradientStop Color="Black"/>
<GradientStop Color="#FF5B5B5B" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
<TextBlock x:Name="textBox1" TextWrapping="Wrap" FlowDirection="RightToLeft" Foreground="White" Padding="5"/>
</Grid>
</StackPanel>
</Button>
</Grid>
</UserControl>
how can I capture the click event when the button is clicked inside gridview?
I tried GridView_ItemClick, GridView1_SelectionChanged in the .cs of the gridview page
I also tried button_Click in the .cs of the usercontrol page
Both didnt work for me. any idea why?
EDIT:
It did work. I just tried to change frame using Frame.Navigate(typeof(PageName));
I cant change frame from usercontrol, I had to send the current frame to the usercontrol in the build function and then change the frame, like this:
Frame frame;
public VideoPreview(Frame f)
{
this.InitializeComponent();
frame = f;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
frame.Navigate(typeof(PlayVideo));
}
Try to look into MVVM pattern http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial and use Commands instead of events.
<Button Command="{Binding SomeActionCommand}" />
This will make your code much cleaner and reliable.
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