I'm trying to convert my old windows forms code into wpf. Each of my windows stored the visibility state, size and position and restored this states on the next run of the application. I connect to the FormCloseQuery event where it was possible to get information about the closereason. This is not possible in WPF.
I can store the position and size in the WPF forms' closing event, but it's not possible to store the visibility state.
Is there an answer how this can be done?
Thanks
Martin
I can store the position and size in the WPF forms' closing event, but it's not possible to store the visibility state.
Poppycock! What's wrong with the Window.Visibility property?:
private void MainWindow_Closing(object sender, CancelEventArgs e)
{
// this.Visibility is the current visibility state of the Window
}
Also, for your information, it is a better idea to handle the Window.Deactivated event to update the values each time the application goes out of focus, or the Window.Closed event to update upon closing. The Closing event is specifically for cancelling the close request.
Furthermore, it is also customary in WPF to store bool values and then data bind them to the Window.Visibility property using the BooleanToVisibilityConverter Class.
Related
How can I detect when a popup is about to be closed?
The Popup class does not have a Closing event in UWP, unlike in WPF where such an event exists.
I need this in order to persist the state of the Popup because the layout can be modified by the user.
As you already know, there is no Closing event. You might get lucky by registering to IsOpen property change (if IsLightDismissEnabled property is set to true...)
this.popup.RegisterPropertyChangedCallback(Popup.IsOpenProperty, (d, e) =>
{
if (!this.popup.IsOpen)
{
// do something, popup is closing?
}
});
because that happens before the LostFocus and Closed events get fired. Other than that, you can redesign the way you persist data to persist them all the time if it's not something very complex to avoid having to depend on the closing event.
In a Windows Forms application, when do I write the code to set the focus to a control both while the application is launched and subsequently after I call a function?
For instance, if I have a DropDownList, a TextBox and four buttons and I want the Focus to be set to the DropDownList, where do I write my code?
To set the focus to a particular control on application launch, I can set the tab index to that DropDown (with a minimum value, under the assumption TabStop property is set to True).
Now, if the user completes an operation (say, any of the Click Button Events) and then I update the DropDown and after that if I want to set the focus...I can do it as
MyDropDownList.Focus()
QUESTION
NB: The question is more about where, not how?
By far the simplest solution is to set the TabIndex property correctly so that your 'MyDropDownList' control has the lowest index. The next approach is to do it in the constructor. But you have to use Select(), the Focus() method cannot work yet because the control doesn't become visible until later.
Public Sub New()
InitializeComponent()
MyDropDownList.Select()
End Sub
Works in the Load event as well. Focus() starts working in the Shown event.
When the parent window is activated (that is, when it receives the "Activated" event), set the focus to the child control where you want the focus located.
private void Form_AddAppID_Activated(object sender, EventArgs e)
{
textID.Focus();
}
Note that the tab order has nothing to do with where the focus starts. Instead, the tab order is used to decide how the focus gets transferred when the user hits the tab key.
I have a full screen WPF application built for a touch monitor, and I have some ListBoxes on the main screen.
When I flick the Listbox it scrolls fine, but when it gets to the end of the list, the entire application gets pulled down from the top of the screen, But I need the inertia just for the list box not for the entire window. How I can achieve that?
The ManipulationBoundaryFeedback event enables applications or
components to provide visual feedback when an object hits a boundary.
For example, the Window class handles the ManipulationBoundaryFeedback
event to cause the window to slightly move when its edge is
encountered.
So, a way around it is to handle ManipulationBoundaryFeedback on the ListBox, and set Handled to true:
<ListBox ManipulationBoundaryFeedback="OnManipulationBoundaryFeedback">
// ...
</ListBox>
Code-behind:
private void OnManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e)
{
e.Handled = true;
}
I'm new to the c# programming language, and I seem to have gotten by pretty swell up until this.
How can I start my program without having one of my panels automatically run its paint method, I want for my panel to stay blank and wait for the users input, but instead its paint method keeps getting called on on start up.
Currently I have found that simply not adding the event until after the button is clicked works, but somehow I feel that isn't the "proper" way to go about this.
Hard to say without seeing some of your existing code, but here's a few possibilities.
Create some class-level boolean variable called didUserEnterInput and set it to "false" initially. When the user enters input, set it to "true". In your paint event, just check the variable.
private void panel1_Paint(object sender, PaintEventArgs e)
{
if (didUserEnterInput)
{
// generate pattern
}
}
You could just hide the panel initially. Set Visible = false (WinForms) or Visibility = Collapsed (WPF). When the user enters input wherever, change the visibility to display the panel.
If this is WinForms, you could just copy the code out of the .designer.cs file and into your code-behind, in a separate method named CreatePanel() or something. Then call that when you need it at runtime to actually display the panel.
Can you explain why this happens? Here are steps to reproduce the exception:
Drag-n-drop a TextBox on a form. Add any other focusable control such as a button on the form.
Add 2 event handlers for that TextBox as follow:
private void textBox_GotFocus(object sender, EventArgs e){
((TextBox)sender).HideSelection = false; //<-- exception highlighted at here.
}
private void textBox_LostFocus(object sender, EventArgs e){
((TextBox)sender).HideSelection = true;
}
Run the form and first click on the textBox, then click on the button then click on the textBox again, and the exception will throw: "Win32Exception - error creating window handle".
The code is simply to make the HideSelection change accordingly when the textBox gets focused and loses focus.
UPDATE
I don't know why is so volatile, I created another project and now the problem is different, there is no exception but an indefinite loop which makes the textbox flicker, the form doesn't seem to responsive, the CPU usage is consumed up to about 17-20%. The last demo is still opened and that demo still has the Win32Exception thrown. Not a clue at all. Now the code of the two projects are the same but the problems are different.
Well, there are a couple of things to note.
First of all, HideSelection doesn't hide or unhide the selection. It specifies, whether the selection will be hidden (or not) when the control loses focus. So it's pointless to change it when the TextBox becomes focus'ed.
What you're doing in LostFocus is default, btw. Why there is an exception in GotFocus is burried within Windows API, I guess. Maybe some undefined state when HideSelection checks inside a focus changed event whether the TextBox has focus or not or tries to hide the selection which is not shown.
Edit: It's not the Windows API on the first hand, but the framework. It tries to "recreate the handle" in the setter of HideSelection if it is changed (don't know why yet - would have to analyse sources) and seems to fail (don't know why either).
Edit2: Finally there's some problem in Win32 DestroyWindow - which leads to skipping the creation of the new window. Maybe because the old one is "in use" in the focus change events?
Interestingly, as soon as the exception occurs (for me), the LostFocus event is fired, immediately followed by GotFocus which throws another exception a.s.o. thus blocking the GUI. Both assignments to HideSelection throw the exception.
Also, when you click the TextBox, any selection is deselected automatically. This, however, is not the reason for the problem, because the exception is thrown if you change focus by pressing Tab (whose normal behaviour is to restore focus). But it may be related (state problems).
If you actually want to restore the selection, you could do it like this:
int selStart;
int selLen;
void textBox1_LostFocus(object sender, EventArgs e)
{
selStart = textBox1.SelectionStart;
selLen = textBox1.SelectionLength;
}
void textBox1_GotFocus(object sender, EventArgs e)
{
BeginInvoke((Action)(() =>
{
textBox1.SelectionStart = selStart;
textBox1.SelectionLength = selLen;
}));
}
I repro this crash. You can easily see it going wrong by setting breakpoints on your event handlers, note how they fire over and over again before your program bombs. The explanation is a bit long winded, I'll give the short version first. The MSDN documentation for the LostFocus event gives stern warnings, both a Note and a Caution, pointing out that this is a low-level event that is dangerous. These events are also hidden in the Properties window for that reason. Fix your problem by using the Enter and Leave event instead.
The long version: the TextBox.HideSelection property is rather special. It is related to the way some properties on native Windows controls are specified. These controls are created with the CreateWindowEx() winapi function, it takes a dwExStyle and dwStyle argument, flags that specify style options for the window. The HideSelection property is such a style flag, ES_NOHIDESEL.
That presents a problem when you want to change the property. Difficult because it can only be specified when the native control is created. Winforms does something pretty heroic to deal with that limitation, it destroys the native control and re-creates it.
That can have pretty interesting side effects, to put it mildly. Most are not observable, but you do for example see the window on the screen getting destroyed and recreated. That's why it flickers. The core problem with your code is, inevitably, because the native window is getting destroyed it also loses the focus. So the LostFocus event immediately fires, right after you got the GotFocus event. Which does something unfortunate, it again changes the HideSelection property. Which forces Winforms to recreate the native control again.
This repeats over and over again when your GotFocus event handler yet again runs for the new native control. This does eventually end when Windows puts a stop to it and doesn't allow any more native windows to be created, it pulls the plug at 10,000 controls after a while. Which generates the "Error creating window handle" exception.
The Enter and Leave events should always be used for focusing events, they only fire if the user actually moved the focus, and don't fire when it happened because of other reasons, like this one. Also notable is that there's no point at all in changing the HideSelection property like you do, the property only has an affect when TextBox doesn't have the focus. The selection is never hidden when it has the focus. So the proper fix here is remove these event handlers and simply set the HideSelection property to True in the Properties window. The default value.
Cant reproduce this works for me:
private void textBox1_Leave(object sender, EventArgs e)
{
((TextBox)sender).HideSelection = false;
}
private void textBox1_Enter(object sender, EventArgs e)
{
((TextBox)sender).HideSelection = true;
}