Window shown event in WPF? - c#

I want to apply fade animation every time my window is shown. How to do that from xaml? That window can be hidden and then shown again so I can't use Loaded event.

You can use the ContentRendered event or override OnContentRendered virtual method like this:
bool _shown;
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
if (_shown)
return;
_shown = true;
// Your code here.
}

You could use the
IsVisibleChanged
Event from the WPF Window;
Then in the EventMethod use:
if((bool)e.IsVisible)
{
// It became visible
}
else
{
// It became hidden
}
This works with opening a new Window instance, this.Show(), this.hide(), this.Close()

Related

check whether a button in another window is clicked

I want to open a window if a button is clicked, and that button is located in another window.
So how to check whether a button in another window is clicked or not?
Now I am coding in a class called 'RightButton.cs'
I want to open a window called 'PopUp' when 'Add' button in 'Reason' window is clicked.
PaidOutReason paid = new PaidOutReason(trnprt, apiParameters);
paid.ShowDialog();
if (paid.btnSave.ClickMode == new ClickMode())
{
PopUpBanks popu = new PopUpBanks(this);
popu.Show();
}
This one was working perfectly, but I had to remove ShowDialog() and replace it with Show(). Then it was not working.
This is for a POS system. It has a user Control called 'Keyboard'. When the 'Reason' window is opening this Keyboard also want to be opened. Therefore I had to replace ShowDialog() with Show().
I'd add an event to the window, and bind an event handler to it.
class WndWindow{
BtnPaid_Click(object sender, EventArgs e){
using(var paid = new PaidOutReason()){
paid.BtnAddClick += Paid_BtnAddClick;
paid.ShowDialog();
paid.BtnAddClick -= Paid_BtnAddClick;
}
}
Paid_BtnAddClick(object sender, EventArgs e){
var popu = new PopUpBanks();
popu.Show();
}
}
class PaidOutReason{
public event EventHandler BtnAddClick;
BtnAdd_Click(object sender, EventArgs e){
//Do standard event handler code
BtnAddClick?.Invoke(this, e);
}
}
If there's any sort of checks you need to perform you can do that before reading the event, and simply return if checks fail.
You can use static controlls in your app. Start with declaring static window object in App.xaml.cs, for example
public static PaidOutReason paidOutWindow;
then, in App constructor method, after InitializingComponent(), initialize static window class:
paidOutWindow = new PaidOutReason();
You may wonder what it gives to you. Since it's POS application, you are likely to use the same set of windows quite often and repeatedly, means you can hold window object in memory and refer to it (and change, when needed). Also, after doing such thing, you will have access to all structures inside PaidOutReason object, by typing
App.paidOutWindow.FunctionName();
and finally, you should have access to all window functions such as ShowDialog().
If you are using MVVM pattern, then you can use command binding for showing the PopupBanks window.
For example:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ICommand AddCommand { get; set; }
public ViewModel()
{
AddCommand = new RelayCommand(AddCommandHandler);
}
private void AddCommandHandler()
{
IPopUpBanks popu = new PopUpBanks(this);
popu.Show();
}
}
PaidOutReason view:
1. <Button x:Name="Add" Command={Binding AddCommand}/>
2. Set the above viewmodel as datacontext of PaidOutReason view.
Create a interface IPopUpBanks containing Show() method and implement this interface on PopUpBanks view.
Handle the Click event of btnSave:
PaidOutReason paid = new PaidOutReason(trnprt, apiParameters);
paid.btnSave.Click += (ss, ee) =>
{
PopUpBanks popu = new PopUpBanks(this);
popu.Show();
};
paid.Show();
Instead of the Keyboard Window, I made it a user control and then initialized an event in there. Then I insert that Keyboard User Control to the PaidOutReason Window and then called the event. Then I was able to use ShowDialog() to call the window.

Best way to intercept closing of window?

I'm looking for the best way to intercept the closing of a window in my software. For example I want to intercept the closure of a form called "settings", and not the MainWindow. vb.net of the procedure was very simple, I had only to call its closing event, but with WPF I can not understand why this event is not captured, and as a result, the code inside is not executed.
In the form you want to intercept the closing for:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if(dontClose)
{
e.Cancel = true;
}
base.OnClosing(e);
}
Replace dontClose with your conditions for not closing.
In the cs file behind your XAML, add this:
// Constructor
public SettingsWindow()
{
InitializeComponent();
Closing += SettingsWindow_Closing; // Subscribe to window closing event.
}
// Window closing event handler.
private void SettingsWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// Add method you want to run on close here.
}
You can acces it from the view model as well if you have one. Like this
Application.Current.MainWindow.Closing += (s, e) =>{ your code comes here};

Devexpress PopupMenu Closing event like Windows Contextmenu Closing event

I am using Devexpress PopupMenu to show on right click. Now I want to know before closing of this popup menu, just like Windows ContextMenu Closing event.
PopupMenu has Closeup event, but that fires after closing of it. Actually my goal is to handle when to close the popup menu according to situations.
Is there anyway, I can achieve it?
I found this previous issue - somebody tried to do the same thing using XtraBars.PopupMenu and had to create a subclass of BarManager and override the BarSelectionInfo.ClosePopup event (maybe you can adapt it to your scenario). The example project is attached to the issue and demonstrates selecting a date in the popup menu and the menu staying open.
EDIT:
Here's the relevant code for completeness - whenever the popup is about to close, ClosePopup fires, as per docs for BarManager :
When you place a BarManager on a form at design time, all controls
publish the PopupContextMenu extender property (its caption in the
Properties window looks like 'PopupContextMenu on barManager1')
You can assign the Context menu using this property and implement the override.
In the example, you return from the method based on some condition (cancel the event) - in this case the Tag of the Bar is set to False on an event in the Form and checked in the override.
private void barEditItem1_EditValueChanged(object sender, EventArgs e) {
popupMenu1.Manager.Bars[0].Tag = false;
}
using DevExpress.XtraBars;
using DevExpress.XtraBars.ViewInfo;
public class MyBarManager : BarManager {
protected override BarSelectionInfo CreateSelectionInfo() {
return new MyBarSelectionInfo(this);
}
}
public class MyBarSelectionInfo : BarSelectionInfo {
public MyBarSelectionInfo(BarManager manager)
: base(manager) {
}
public override void ClosePopup(IPopup popup) {
if (!(bool)Manager.Bars[0].Tag) {
Manager.Bars[0].Tag = true;
return;
}
base.ClosePopup(popup);
}
}

reloaded wpf window

I have main wpf window, in this window I create new slave windows and add in dictionary. It is possible, after closing the slave window, it showed once again.
public class MainWindow:Window
{
private dictionary<string, SlaveWindow> _winDic= new dictionary<string, SlaveWindow>();
public void SomeMethod()
{
var mySlaveWindow = new SlaveWindow();
//add to dictionary
_winDic.Add("mySlaveWindow",w);
//close slave window w
//show
_winDic[mySlaveWindow].Show();
}
}
This following way of doing this is taken from this msdn page.
Subscribe to the Closing event for the Window and add this in code behind.
private bool m_close = false;
// Shadow Window.Close to make sure we bypass the Hide call in
// the Closing event handler
public new void Close()
{
m_close = true;
base.Close();
}
private void Window_Closing(object sender, CancelEventArgs e)
{
// If Close() was called, close the window (instead of hiding it)
if (m_close == true)
{
return;
}
// Hide the window (instead of closing it)
e.Cancel = true;
this.Hide();
}
This will make sure your Window finally closes and is not left hanging.
You'll need to hide the window rather than closing it.
If you call Hide(), the window will vanish like it would when you call Close() but you'll be able to reshow it later by calling Show() again.

How to dismiss a popup in Silverlight when clicking outside of the control?

In my Silverlight UI, I have a button that when clicked pops up a control with some filtering parameters. I would like this control to hide itself when you click outside of it. In other words, it should function in a manner similar to a combo box, but it's not a combo box (you don't select an item in it). Here's how I'm trying to capture a click outside of the control to dismiss it:
public partial class MyPanel : UserControl
{
public MyPanel()
{
InitializeComponent();
}
private void FilterButton_Click(object sender, RoutedEventArgs e)
{
// Toggle the open state of the filter popup
FilterPopup.IsOpen = !FilterPopup.IsOpen;
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
// Capture all clicks and close the popup
App.Current.RootVisual.MouseLeftButtonDown += delegate {
FilterPopup.IsOpen = false; };
}
}
Unfortunately, the event handler for MouseLeftButtonDown is never getting fired. Is there a well-established way of making a popup control that auto-dismisses when you click outside of it? If not, why isn't my MouseLeftButtonDown handler firing?
Solution:
I thought I'd post my entire solution in case others find it helpful. In my top-level visual, I declare a "shield" for the popups, like this:
<UserControl xmlns:my="clr-namespace:Namespace"
x:Class="Namespace.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:uriMapper="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
>
<Grid Background="Black" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<my:MyStuff/>
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
x:Name="PopupShield" Background="Transparent" Width="Auto"
Height="Auto" Visibility="Collapsed"/>
</Grid>
</UserControl>
Then, I added an extension method for the Popup class, like this:
public static class PopupUtils
{
public static void MakeAutoDismissing(this Popup popup)
{
var shield = (App.Current.RootVisual as MainPage).PopupShield;
// Whenever the popup opens, deploy the shield
popup.HandlePropertyChanges(
"IsOpen",
(s, e) =>
{
shield.Visibility = (bool)e.NewValue
? Visibility.Visible : Visibility.Collapsed;
}
);
// Whenever the shield is clicked, dismiss the popup
shield.MouseLeftButtonDown += (s, e) => popup.IsOpen = false;
}
}
public static class FrameworkUtils
{
public static void HandlePropertyChanges(
this FrameworkElement element, string propertyName,
PropertyChangedCallback callback)
{
//Bind to a depedency property
Binding b = new Binding(propertyName) { Source = element };
var prop = System.Windows.DependencyProperty.RegisterAttached(
"ListenAttached" + propertyName,
typeof(object),
typeof(UserControl),
new System.Windows.PropertyMetadata(callback));
element.SetBinding(prop, b);
}
}
The extension method is used like this:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
FilterPopup.MakeAutoDismissing();
}
One way is to put your control on a transparent canvas that fills the entire Silverlight surface. When the canvas is clicked close the canvas and control. It is important to ensure that the Background brush of the canvas is set to "Transparent" if you want to receive mouse events.
An alternate method that I have not had success with is using mouse capture in Silverlight and detecting when the mouse is clicked outside of the popup.
Did you set a background color on your RootVisual?
I just created something similar and hopefully this could be of any help. :)
In my PopUp control, I have a Border which has a Grid that contains a number of textboxes. I named the Border 'PopUpBorder'.
In my UserControl's constructor, I have,
this.PopUpBorder.MouseLeave += (s, e) =>
{
Application.Current.RootVisual.MouseLeftButtonDown += (s1, e1) =>
{
this.PopUp.IsOpen = false;
};
};
And looks like it is working as expected. Please let me know if this doesn't work in your case.
On the first click, call the CaptureMouse() method on the control. Then call ReleaseMouseCapture() on the second click.
The proposed solution uses a special shield canvas to block input to other controls.
This is fine, but I am trying implement a generic control and cannot depend on the existence of such a shield canvas.
The binding of the MouseLeftButtonDown event on the root visual didn't work for me either, because existing buttons on my canvas would still fire their own click event and not the MouseLeftButtonDown on the root visual.
I found the solution in this ice article: Popup.StaysOpen in Silverlight from Kent Boograart.
The main methods for this question are:
private void OnPopupOpened(object sender, EventArgs e)
{
var popupAncestor = FindHighestAncestor(this.popup);
if (popupAncestor == null)
{
return;
}
popupAncestor.AddHandler(Windows.Popup.MouseLeftButtonDownEvent, (MouseButtonEventHandler)OnMouseLeftButtonDown, true);
}
private void OnPopupClosed(object sender, EventArgs e)
{
var popupAncestor = FindHighestAncestor(this.popup);
if (popupAncestor == null)
{
return;
}
popupAncestor.RemoveHandler(Windows.Popup.MouseLeftButtonDownEvent, (MouseButtonEventHandler)OnMouseLeftButtonDown);
}
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// in lieu of DependencyObject.SetCurrentValue, this is the easiest way to enact a change on the value of the Popup's IsOpen
// property without overwriting any binding that may exist on it
var storyboard = new Storyboard() { Duration = TimeSpan.Zero };
var objectAnimation = new ObjectAnimationUsingKeyFrames() { Duration = TimeSpan.Zero };
objectAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame() { KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero), Value = false });
Storyboard.SetTarget(objectAnimation, this.popup);
Storyboard.SetTargetProperty(objectAnimation, new PropertyPath("IsOpen"));
storyboard.Children.Add(objectAnimation);
storyboard.Begin();
}
private static FrameworkElement FindHighestAncestor(Popup popup)
{
var ancestor = (FrameworkElement)popup;
while (true) {
var parent = VisualTreeHelper.GetParent(ancestor) as FrameworkElement;
if (parent == null) {
return ancestor;
}
ancestor = parent;
}
}
I'm still not sure, why this solution works for me and this not:
Application.Current.RootVisual.MouseLeftButtonDown += (s1, e1) =>
{
this.PopUp.IsOpen = false;
};
It looks like the FindHighestAncestor method will just return the root visual? But then the difference must be the event handler?
I guess the main difference is the last parameter of the AddHandler method which is true in the case:
AddHandler(Windows.Popup.MouseLeftButtonDownEvent, (MouseButtonEventHandler)OnMouseLeftButtonDown, true);
The MSDN docs say:
handledEventsToo
Type: System.Boolean
true to register the handler such that it is invoked even when the routed event is marked handled
in its event data; false to register the handler with the default condition that it will not be
invoked if the routed event is already marked handled. The default is false. Do not routinely ask
to rehandle a routed event. For more information, see Remarks.
A simpler alternative (although not exactly what you asked for) would be to close the popup on MouseLeave. MouseLeave on the Popup object itself wont work, but MouseLeave on the highest level container within the Popup does.
i have posted a solution for this on my blog, you can see the post here -
Silverlight: close Popup on click outside. as you can see the use is very simple - it is an attached property you add on your popup. you do not have to add any wrappers, you do not have to take care if you do or do not have some background color... my code will take care of it all.

Categories

Resources