I would like to use a BaseWindow for other windows in WPF, but I'm getting errors that I don't know how to fix.
I created a base class:
namespace Evolutio.FluXus.WPFApp
{
public partial class WindowBase : Window
{
}
}
And changed my LoginView.xaml.cs:
public partial class LoginView : WindowBase, ITransientDependency
{
private readonly IUserAppService _userAppService;
public LoginView(IUserAppService userAppService)
{
_userAppService = userAppService;
InitializeComponent();
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
And I'm getting an error in the Close() statement.
Can anyone help me?
You also have to inherit WindowBase in the other part of of your parial LoginView class (the Xaml code):
<local:WindowBase x:Class="WpfApplication1.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:Evolutio.FluXus.WPFApp"
Related
I have the problem that I want to add an event from XAML directly to another class.
The standard class, which is used, is the MainWindow.
In my situation I want to define, which class should be used for the event.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Closing_Event(object sender, System.ComponentModel.CancelEventArgs e)
{
}
}
public class differentClass
{
public differentClass()
{
}
private void Window_Closing_Event(object sender, System.ComponentModel.CancelEventArgs e)
{
}
}
Maybe someone can help me, how I can use the event from the second class without any code in the MainWindow.
There is a Behavior class for this purpose. You will need to add the reference to the System.Windows.Interactivity in the project: How to add System.Windows.Interactivity to project?
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
public class CustomWindowHandlerBehavior: Behavior<Window>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Closing+= Window_Closing_Event;
}
protected override void OnDetaching()
{
AssociatedObject.Closing-= Window_Closing_Event;
base.OnDetaching();
}
private void Window_Closing_Event(object sender, System.ComponentModel.CancelEventArgs e)
{
//...
}
}
using this behavior in XAML:
<Window
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity">
<i:Interaction.Behaviors>
<local:CustomWindowHandlerBehaviour />
</i:Interaction.Behaviors>
<Window/>
I have a wpf project without StartupUri. I set the MainWindow as TestWindow in app.cs. But i can't use the DoNothing method. How can i access to methods of TestWindow?
MainWindow.DoNothing(); //No such method. Get error when try to build
Project:
TestWindow.cs
public partial class TestWindow : BaseWindow
{
...
public void DoNothing()
{
return;
}
...
}
app.xaml
<Application x:Class="Test.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test"/>
app.cs
...
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow = new TestWindow();
}
...
Cast MainWindow to your type:
(MainWindow as TestWindow)?.DoNothing();
Or store a reference to the TestWindow in a variable of your own and access the window directly using this one:
public partial class App : Application
{
private readonly TestWindow testWindow = new TestWindow();
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow = testWindow;
...
testWindow.BeginInit();
}
}
I am not familiar with using event handlers, and I was wondering if anyone had or could direct me to some code that shows how to use an event handler that will execute code on the Close/Closed event?
I know this can be done because of this answered question:
Run code on WPF form close
But I need some direction.
Thank you =)
It's just this XAML
<Window ... Closing="Window_Closing" Closed="Window_Closed">
...
</Window>
and code for both the Closing and Closed events
private void Window_Closing(object sender, CancelEventArgs e)
{
...
}
private void Window_Closed(object sender, EventArgs e)
{
....
}
If you want to do it all from code behind put this in your windows .cs file
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Closed += new EventHandler(MainWindow_Closed);
}
void MainWindow_Closed(object sender, EventArgs e)
{
//Put your close code here
}
}
}
If you want to do part in xaml and part in code behind do this in 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" Closed="MainWindow_Closed">
<Grid>
</Grid>
</Window>
and this in .cs
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
void MainWindow_Closed(object sender, EventArgs e)
{
//Put your close code here
}
}
}
The above to examples you can apply to any form in a xaml app. You can have multiple forms. If you want to apply code for the entire application exit process modify your app.xaml.cs file to this
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnExit(ExitEventArgs e)
{
try
{
//Put your special code here
}
finally
{
base.OnExit(e);
}
}
}
}
You can override the OnExit function in App.Xaml.cs like this:
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnExit(ExitEventArgs e)
{
//do your things
base.OnExit(e);
}
}
If you are using C# on Microsoft Visual Studio, the following worked for me.
In your Window.cs file
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace Name_Space
{
public partial class Window : Form
{
public Window()
{
InitializeComponent();
//...
}
private void Window_Load(object sender, EventArgs e)
{
//...
}
private void Window_Closed(object sender, EventArgs e)
{
// Your code goes here...!
}
}
}
In your Window.Designer.cs file add this line to the following method
...
private void InitializeComponent()
{
...
//
// Window
//
...
this.Closed += new System.EventHandler(this.Window_Closed); // <-- add this line
}
...
I have a Main Window which includes some User Controls that are initialized in the WPF XAML
MainWindow.xaml.
<Grid>
<local:RegularUnit x:Name="ucRegularUnit" Grid.Row="0" />
<local:Actions x:Name="ucActions" Grid.Row="1" />
// .....
</Grid>
I have a public function in the Main Window which I want to call after clicking a Button in my User Control. After searching for some solutions, I found a way to get the parent window instance in my User Control class, but it can't find the function when I'm using parentWindow.myFunction().
User Control RegularUnit.cs:
public partial class RegularUnit : UserControl
{
public RegularUnit()
{
InitializeComponent();
}
private void Button_SearchSerialNumber_Click(object sender, RoutedEventArgs e)
{
Window parentWindow = Window.GetWindow(this);
//parentWindow. //Can't find the function myFunction()
}
}
MainWindow.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void myFunction()
{
// Do Some Stuff...
}
}
What am I doing wrong, and how can I fix it?
You can't call myFunction on parentWindow because it's not a member of the standard WPF Window class but of your custom MainWindow.
What you could do is to cast the result of Window.GetWindow(this) to MainWindow, like
MainWindow parentWindow = (MainWindow) Window.GetWindow(this);
parentWindow.myFunction();
However this is a really bad class design because now your user control depends on being embedded in a specific window.
What you should rather do is to add an event to the user control on which the parent control can subscribe to.
public event EventHandler SerialNumberSearch;
private void Button_SearchSerialNumber_Click(object sender, RoutedEventArgs e)
{
var handler = SerialNumberSearch;
if (handler != null) handler(this, EventArgs.Empty);
}
Of course you could use a different kind of EventHandler, depending on what you need.
System.Windows.Application.Current.Windows.OfType<YourWindow>().SingleOrDefault(x => x.IsActive).YourPublicMethod();
Although the above code is a messy way of doing it, but it gets the job done nevertheless.
Solution based on event subscription as suggested by Dirk. I have based event on a simple delegate but you can follow similar pattern and base it on a delegate that suits your scenario.
// In UserControl
namespace TextEditor
{
public partial class TextEditorToolBar : UserControl
{
// you can use Action type delegate also
public delegate void getDocumentKeywords();
public event getDocumentKeywords getDocumentRakeKeywordsEvent;
public TextEditorToolBar()
{
InitializeComponent();
}
// This is event handloer for the button on your user control
private void ExtractRakeKeywords(object sender, RoutedEventArgs e)
{
var handler = getDocumentRakeKeywordsEvent;
if (getDocumentRakeKeywordsEvent != null)
getDocumentRakeKeywordsEvent();
}
}
}
// In MainWindow
namespace TextEditor
{
public partial class MainWindow : Window
{
private DocumentKeywordsExtractor KeyWordsExtractor;
public MainWindow()
{
InitializeComponent();
KeyWordsExtractor = new DocumentKeywordsExtractor(richTextBox);
// toolbar is the name given to UserControl in MainWindow.xaml
toolbar.getDocumentRakeKeywordsEvent += ExtractRakeKeywords;
}
private void ExtractRakeKeywords()
{
KeyWordsExtractor.GetRakeKeywords();
}
}
I have a WPF app, in file Main.xaml.cs I have the following constructor:
public MainWindow()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
from another class:
In App.xaml.cs
I need to fire an event which will make run method MainWindow_Loaded in Main.xaml.cs
Any idea how to do it?
You can do this by manually creating the MainWindow in your App class. To do it, remove the StartUp attribute from the App.xaml so that it looks like this...
<Application x:Class="Anything.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
</Application>
In your App.xaml.cs class, override the OnStartup method like this...
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow mw = new MainWindow();
mw.Loaded += mw_Loaded;
mw.Show();
}
void mw_Loaded(object sender, RoutedEventArgs e)
{ // loaded event comes here
throw new NotImplementedException();
}
}
This override manually creates the MainWindow and shows it. It also subscribes to the Loaded event and receives the notification in the mw_Loaded method. You can also call the window's method directly because you have the window instance.
Alternatively, you can overload the MainWindow constructor and pass it an Action delegate. It would look like this...
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow mw = new MainWindow(DoSomething);
mw.Show();
}
public void DoSomething()
{
}
}
And the MainWindow would look like this...
public partial class MainWindow
{
private readonly Action _onLoaded;
public MainWindow(Action onLoaded)
{
_onLoaded = onLoaded;
InitializeComponent();
Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
_onLoaded();
}
}
That gives you two alternatives, there are other ways also, but these are the most expedient. As Sheridan pointed out, tinkering with a window's loaded event can have confounding side effects, like re-entrancy. The WPF forefathers envisioned it as a lifetime event.