I have a user control which is having a listview inside it. The SelectionChanged event of this list view is handled inside the user control. The code for the same is as follows:
private void lstvMyView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{...}
I want to call this handler again from some other place inside the user control. So to call this handler i need the "SelectionChangedEventArgs" there. When I am trying to create the instance of "SelectionChangedEventArgs", i am unable to understand what should I pass as parameters to the constructor of "SelectionChangedEventArgs".
The place from where I am suppose to call this handler does not add or remove any items in the listview. It just navigates in the items in the listview thereby changing the selectedindex of the listview.
I am trying to do something like this. The below code is obviously incorrect.
lstvMyView_SelectionChanged(_lstvMyView, new SelectionChangedEventArgs());
I want to call this handler again from some other place inside the user control
Don't. An event handler is not supposed to be called explicitly from your code. Whatever you're doing in this handler, you can put it in another method that only takes the parameters it needs, and call that method from your code.
The SelectionChangedEventArgs can be instantiated for unit testing as follows:
new SelectionChangedEventArgs(
System.Windows.Controls.Primitives.Selector.SelectionChangedEvent,
new List<CustomViewModel> { },
new List<CustomViewModel> { customViewModel }
)
Beware that both the removedItems and addedItems cannot be null so an empty collection should be passed.
Related
I was searching all over the place but I couldn't find an answer. I need to fire up an ListView item action, so it would rise the ItemActivate event. For now, it's only possible using ENTER key or double click... I would like to know if I could programmatically do that, something like :
listView.Items[int].Activate();
This doesn't work of course, because that function Activate() is not implemented there. For example, I couldn't find how to trigger buttons programmatically, but there it was, in the context menu which appears while you type:
buttonX.PerformClick();
...and it would trigger the button_click event. I wonder if there's something similar in the ListView control for triggering items inside of it ? I want it to raise this event programmatically and not by mouse doubleclick or Enter key on the keyboard...
private void myListView_ItemActivate(object sender, EventArgs e)
{
MessageBox.Show("hello");
}
According to the documentation, the EventHandler in the ListView should be public. So you can raise the event with:
myListView.ItemActivate(myListView, EventArgs.Empty);
This way everyone who subscribed to this event will get notified.
Another way, of course, is to directly call your method:
myListView_ItemActivate(this, EventArgs.Empty);
But this doesn't really classify as "raising the event", because you actually don't raise an event. You just call a method.
When I set the .ItemSource() property on a DataGrid to a Collection, the call returns fast, but the actual binding happens afterwards. Since I want to display a waiting cursor, I need to detect when the actual binding has finished. Is there any event for this?
Anything based on ItemsControl uses an ItemContainerGenerator to generate its items in the background. You can access the ItemContainerGenerator property of the DataGrid and hook up the StatusChanged event to determine when it's done. If you're using virtualization and scroll, this will fire again so you need to handle that if necessary in your case.
I waited for my DataGrid's Loaded event to fire, and I did a BeginInvoke, like this:
private void SubjectsList_Loaded(object sender, RoutedEventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => ColorMyRows()));
}
More details available in my answer here: https://stackoverflow.com/a/44464630/2101117
Your best bet is to hook into OnPropertyChanged event in your Window or User Control. This event is fired every time a property is updated. Then check for the actual property you wish to observe and take action.
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
if ("YOUR_PROPERTY_NAME".Equals(e.Property.ToString()))
{
// Take action
}
base.OnPropertyChanged(e);
}
I'm creating a simple editor within our application using the WPF RichTextBox. Above it I've added the reguslar buttons like Bold, Italic, etc. These buttons use the RichTextBox's commands to set these properties, but next to these buttons, the commands also get send with CTRL+B, CTRL+I, etc. I want these buttons to represent the current state of the RichTextBox at the cursor. I already found out how to get this state and it works when I update this state on the SelectionChanged event. This event ofcourse isn't fired when Bold is toggled so there is no direct feedback.
I would like to know if there is a way to listen to the commands being called, without affecting its original behaviour or some other ideas to solve my problems.
I tried listening to the command the following way:
CommandBinding boldBinding = new CommandBinding(EditingCommands.ToggleBold, CommandExecuted);
_richTextBox.CommandBindings.Add(boldBinding);
and
private void CommandExecuted(object sender, ExecutedRoutedEventArgs e) {
UpdateProperties();
e.Handled = false;
}
This did update the properties, but the RichTextBox didn't seem to receive the command anymore.
I also tried to make my own commands on the control containing the RichTextBox, but when CTRL+B is pressed when the RichTextBox has focus, the original RichTextBox commands are called instead of the new one.
Many thanks in advance!
Liewe
In order to listen to the commands being called, you can use the events raised by CommandManager: Executed or PreviewExecuted.
If you change your XAML to:
<RichTextBox x:Name="_richTextBox" ...
CommandManager:PreviewExecuted="OnRichTextBoxCommand" ... />
you get the OnRichTextBoxCommand method called right before the command is executed. Unfortunately, using the Executed attached event does not work.
This method is called for each event, so you have to filter them:
private void OnRichTextBoxCommand(object sender, ExecutedRoutedEventArgs e) {
if (e.Command == EditingCommands.ToggleBold) {
UpdateProperties();
}
}
It may be even a bit more complex, as the current selection may not have changed when this method is called, so you have to post yourself a message, e.g. like this:
Dispatcher.BeginInvoke(new Action(UpdateProperties));
(if you reference already System.Core, you have the Action type, otherwise define a delegate taking no parameter and returning void, and use in instead.)
is there a way I can get a Load event for System.Windows.Forms.Control just like System.Windows.Forms.Form.Load?
I want to run some initialize code before the control first shown.
Also, it would be nice to be able to do the same for System.Windows.Forms.ToolStripStatusLabel which is not actually a Control, but works like one.
Ideally, I can do this:
control.OnLoad(() => { dosomething here; });
in which OnLoad is a extension method that would run the argument Action when the "control" "Loads".
Thanks!
Form.Load event is called by the OnLoad method which is called from the OnCreateControl method which belongs to the Control class. So for the form the calling sequence would be following:
OnCreateControl start
OnLoad start
Form Load event call
OnLoad finish
OnCreateControl finish
I guess you can override OnCreateControl for your component and add your optimization code there.
Hope this helps, Regards.
For a control you can override either OnControlCreated or OnHandleCreated. The latter one can fire multiple times if it is necessary to recreate the control window. Be sure to use it if your code affects the window itself. In other words, if you do anything that requires the Handle property.
Few suitable choices for a ToolStripItem derived control. I'd recommend overriding SetVisibleCore() or OnAvailableChanged() or the AvailableChanged event. They run when the Visible property of the ToolStripItem changes. Beware that it may fire multiple times, keep a bool field that tracks that your initialization code has already run.
Last but not least, be sure to only do any of this if your code actually requires the control to be created. The vast majority of init code can go in the constructor. You only need a Load event if your code depends on the actual Location and Size of the control. Which might be different from the designer value if the form rescales itself due to a different system font or video DPI setting on the target machine.
I needed a solution like this for a TabPage within a TabControl.The only thing I came up with was using the paint event handler. I added the event handler for Paint and in the very first line I remove the event handler and then do more initialization code. This only works if you do nothave any custom painting. Alternatively, if you do need to do custom painting you could add a flag to check for each time Paint Executes.
//Paint only runs once
private void tabPage1_Paint(object sender, PaintEventArgs e)
{
tabPage1.Paint -= tabPage1_Paint;
//Do initialization here
}
/////////////////////////////////////////////////////////////////////////////////
//Paint always runs
private bool IsFirstPaint = true;
private void tabPage1_Paint(object sender, PaintEventArgs e)
{
if(IsFirstPaint)
{
IsFirstPaint = false;
//Do initialization here
}
//Do custom painting here
}
When the user clicks on certain part of a window, I add a UserControl to the window's controls. The UserControl has a close button. What can I do in the UserControl's button handler to destroy the UserControl? There seems to be no .net analog to the Win32 DestroyWindow call, and there is no Close() method for a control. So far I have this:
private void sbClose_Click(object sender, EventArgs e)
{
Parent.Controls.Remove(this);
this.Dispose();
}
And, in case the parent needs to destroy the control, what are the steps? This is what I have so far:
Controls.Remove(control);
control.Dispose();
You're working in a managed code environment with garbage collection - there's nothing you can do to force the user control to be destroyed.
All you need to do, all you can do is to remove it from the parent and make sure there are no remaining references.
This will generally be sufficient:
private void sbClose_Click(object sender, EventArgs e)
{
Parent.Controls.Remove(this);
}
The only time you'll need more is if you tie things together with events, as you'll need to deregister those as well.
A control can't destroy itself. In terms of having a parent do it, you are on the right track. You can have the parent or another control call Dispose on it and remove all references to this control. Dereferencing the control this way will allow the GC to clean things up.