WPF mainwindow content load from a page - c#

I have one MainWindow and one page
I load the page content into the mainwindow by that code
NewPage abt = new NewPage();
this.Content = abt;
but how can I unload the page (reload the mainwindow control and close the page)
if I use the same code to load mainwindow content I get a runtime error

The way I have done this is to have a Frame in the XAML like so:
<Frame Grid.RowSpan="4" Grid.ColumnSpan="3" x:Name="_NavigationFrame" NavigationUIVisibility="Hidden"/>
And then I can set a page and unload a page with this:
_NavigationFrame.Navigate(customPage);
//code to hide main page controls
_NavigationFrame.Navigate(null);
//code to make main page controls visible

I don't think loading page into MainWindow content is a good solution, but if You need it You could probably get current state and save it to some property(or some other thing like xml file) before changing. Like Below:
public partial class MainWindow()
{
FrameworkElement previousContent; // I believe Content property is of FrameworkElement type
public MainWindow()
{
...
}
...
public void ChangeContent()
{
previousContent = this.Content; // save state
NewPage abt = new NewPage();
this.Content = abt; // set new state
}
//And later You can restore this state by:
public void RestorPreviousContent()
{
this.Content = previousContent;
}

Related

Cast Page for accessing textbox/object of other page

Previously, I had only one xaml-file, which was the only Windows, namely the mainWindow.
To access any button / textbox / object from another class (explicetly a non-static class) I can just cast the Window like this
mainWindow mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(w => w is mainWindow) as mainWindow;
Now my question is, how does this work for several pages, since now I have a Frame, where I load several pages to.
Actually it does NOT work like this:
myPage page = Application.Current.Windows.Cast<Page>().FirstOrDefault(p => p is myPage) as myPage;
There is a runtime-error, which says:
System.InvalidCastException: Object of type "namespace.mainWindows" cannot be converted to object of type "System.Windows.Controls.Page"
make MainWindow return a Page, which is displayed:
public class mainWindow
{
public Page GetCurrentPage()
{
// return known Page;
};
}
and then:
mainWindow mainWin = Application.Current.Windows.OfType<mainWindow>().FirstOrDefault();
Page p = mainWin?.GetCurrentPage();
This one worked out for me:
MainWindow
namespace myName
{
public partial class main : Window
{
public main()
{
// ...
}
}
}
Textbox and Frame, where the page is load into, in the xaml-file of the mainWindow
Note, the FieldModifier is set to public!
<TextBox x:Name="textbox_main" Text="testString main" x:FieldModifier="public"/>
<Frame x:Name="myFrame" x:FieldModifier="public"/>
Page
namespace myName
{
public partial class myPage : Page
{
public myPage()
{
// ...
}
}
}
Textbox in the xaml-file of the Page
Note, the FieldModifier is set to public!
<TextBox x:Name="textbox_page" Text="testString page" x:FieldModifier="public"/>
After that, one is able to access the two textboxes (one directly in the window, one in a page of the window) in any other class via the following commands:
// get instance of the main-Window
main mainWin = Application.Current.Windows.Cast<Window>().FirstOrDefault(w => w is main) as main;
// Access objects of the main-Window
Console.WriteLine(mainWin.textbox_main.Text);
// get instance of the current page of the certain frame
myPage page = (myPage)Application.Current.Windows.OfType<main>().FirstOrDefault().myFrame.Content;
// Access objects of the page
Console.WriteLine(page.textbox_page.Text);

How to set title of a page that hosted by a frame window?

I have a frame window that are used to host pages.
//inside frame window
public partial class FrameWindow : Window
{
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Main.Content = new Example_Page();
}
}
I saw this solution but its not worked since the page hosted by a window frame. So how do i set a title of a page and display on the top bar of the window? thank you
You can make your Example_Page expose a property (for example Title) that denotes the title and then make the FrameWindow Title property bind to that property. An example:
In the markup for your FrameWindow bind the title like this:
<Window ...
Title="{Binding Content.Title, RelativeSource={RelativeSource Self}}">
And in your Example_Page code behind expose a property like this:
public partial class Example_Page : ....
{
...
public string Title { get; set; }
...
}
Note that if you set the Content of the FrameWindow to any content that doesn't expose this property the Title will be blank.

How to pass window and string parameter from code behind into User Control

I have a bit off header that I need global to a few files so I have made a user control (I can't use the main window as this isn't global to all files) however there's two parameters that my user control needs, ScreenName and MainWindow to navigate on the home button click. Here is what I have tried so far:
public Header(MainWindow mainWindow, string screenName)
{
InitializeComponent();
DataContext = this;
ScreenName = screenName;
MainWindow = mainWindow;
ScreenNameTextBlock.Text = ScreenName;
}
public string ScreenName { get; set; }
public MainWindow MainWindow { get; set; }
private void Hyperlink_OnClick(object sender, RoutedEventArgs e)
{
//need to navigate home here
MainWindow.LoadScreenByCode("Menu");
}
You can probably assume the corresponding XAML as it's just a hyperlink and a textblock, but if you need it let me know.
I can include the user control like so:
<controls:Header x:Name="Header"></controls:Header>
But I can't figure out how to assign the parameters. If I try in the codebehind I can access the values like this:
Header.MainWindow = Shell;
Header.ScreenName = "Name";
But this causes the values to be null. Sorry if this is an easy issue, I am new to UserControls.
To access the main window of your application you should get the running instance of it as the following:
MainWindow myRunnningMainWindow = (Application.Current.MainWindow as MainWindow);
if(myRunningWindow!=null)
{
//Do what you want with the main window
}

How to load ViewModel/View in WPF under CaliburnMicro

I have a timer in my wpf application wich every 5 minutes ask a WCF service. If the service have message for my application, I get a list which contains text data and a specific code.
This code give an information about the view which must be loaded to print the data.
I have two ViewModel (the data source is the same for both): One for a Ticker > one view and One for Popup > two view
Project files :
View
Popup
PopHighView.xaml
PopMediumView.xaml
Ticker
TickerLayout.xaml
TickerNormal.xaml
ViewModel
PopViewModel
TickerViewModel
Models
AlertModel.cs
ViewParsers
AlertParser.cs
Datasource :
public class AlertParser : IAlertParser{
AlertServiceClient service;
public List<AlertModel> TickerAlertData()
{
try
{
service = new AlertServiceClient();
List<AlertModel> items = (from item in service.GetActiveAlert() select new AlertModel
{
Alertid= item.AlertId,
Alertstartdate = item.AlertStartDate,
Alerttitle = item.AlertTitle,
Alerttxt = item.AlertText
}).ToList();
return items;
}
catch
{
return null;
}
}
}
When my application is launched, there is no loaded view, only a icon in the systray(with wpf notifyicon).
My problem is, under theses circonstances, I don't understand how I could loaded a couple ViewModel/View, and pass the data to them, when my timer return a true from my service.
Many examples on the web have a mainview loaded, that's why I'm lost (like Conductor example on caliburn micro page).
Thanks for any help !
Edit :
Ok, My timer look like that :
if (service.IsAlertReady()=true)
{
string hostName = Dns.GetHostName();
string myIP = Dns.GetHostEntry(hostName).AddressList[0].ToString();
service.IsAlertForMe(myIP);
if(service.IsAlertForMe(myIP) == true)
{
ShellViewModel shell = new ShellViewModel();
shell.ShowMediumPop();
}
else
...
ShellViewModel
public class ShellViewModel : Conductor<object>
{
public void ShowMediumPop()
{
ActivateItem(new PopViewModel());
}
}
PopViewModel
public class PopViewModel : screen
{
protected override void OnActivate()
{
base.OnActivate();
}
}
PopView.Medium
<UserControl x:Class="TerminalClientProto.View.PopView"
...
cal:View.Model="{binding}"
cal:View.Context="Medium"
>
I'm sorry but I don't understand how I could launch my view when my Ticker tick. I've read the documentation, but I need some hints to understand this mechanism.
A program, any program, including the very program that contains the views you want to display can show a view in a number of ways. Here's a few:
var app = new App();
app.InitializeComponent();
app.Run();
Or you can start the view directly:
var view = new MyView();
view.Show();
// or
view.ShowDialog();
If the view is a MainWindow, then you can create a ContentControl area within the view to inject the Usercontrol containing the sub-view of what you want displayed. This still requires the MainWindow to be open... So the examples above would also work when injecting UserControls into a MainWindow. The act of injecting a User control is setting the ContentControl's Content to an instance of the User Control itself. Eventhandlers can handle this scenario nicely...
public void NewUserControlInMainWindow(object sender, UserControl uc){
//XCC = the Xaml content control in main window
XCC.Content = uc;
}
I'm not really sure how Caliburn does view injection....

How can I make a form's controls not load until at least the frame of the form has been displayed?

I have a C# Winforms form that has a ton of custom controls that take about 10 seconds to load. Right now, when I click the menu item to open my form, the menu freezes for 10 seconds, and then the form just pops up ready to go. What I'd like to do is the following: As soon as you click the appropriate menu item to open up my form, I want to display the form immediately, but perhaps with just a red background and no controls on it. Then the form can start trying to load all my controls. That way the user sees that their mouse click opened the new form, and it doesn't look like the whole app froze. Moving it to a new thread is not an option.
Have you tried putting your user controls in a seperate user control, then instantiate it in your Shown event and then add it to your form.
i.e. something like this
Form1
public partial class Form1 : Form
{
UserControl1 usr;
public Form1()
{
InitializeComponent();
}
private void Form1_Shown(object sender, EventArgs e)
{
usr = new UserControl1();
usr.Dock = DockStyle.Fill;
panel1.Controls.Add(usr);
}
}
UserControl1
public partial class UserControl1 : UserControl
{
public UserControl1()
{
System.Threading.Thread.Sleep(10000);
InitializeComponent();
}
}

Categories

Resources