SelectedIndexChange event not firing when using through reflection - c#

I have a windows form with a listview control. I have a selectedIndex changed event where i am performing some action. Through reflection I am trying to set the value of the list view.
But the event is not getting fired. Any help will be helpfull.
Edit
The event looks like
private void LV1_SelectedIndexChanged(object sender, EventArgs e)
{
if (LV1.SelectedItems.Count>0)
{
if (LV1.SelectedItems[0].Text.ToString() == "testing")
{
// Do some work.
}
}
}
I am using relection in another project and changing the selected item as follows
Assembly a = Assembly.LoadFrom(exePath);
Type formType = a.GetType(formName);
testForm = (Form)a.CreateInstance(formType.FullName);
if (testForm != null)
{
Type t1 = testForm.GetType();
FieldInfo fi = t1.GetField(controlName, flags);
object ctrl = fi.GetValue(testForm);
ListView l1 = (ListView)ctrl;
l1.Items[0].Selected = true;
}

Automating another application is fun howver not a trivial task. There's a few options but I guess most of them is out of scope for you. One would be to programatically take over the mouse and keyboard and trough those channels manage the program. Another way would be to manipulate memory, As I said neither are trivial to implement and very easily broken if the aplpication is updated.
I would suggest instead of trying to automate the application to look for infliction points. Are there any service endpoints you could automate and achieve the same result? any API or dll's used by the application you could use instead?
If you really have to automate the application there do exist several frameworks for doing that (usually build for testing purposes). The only one I can think off right now is made by Assima as is ment for training purposes.

I think your problem is here:
testForm = (Form)a.CreateInstance(formType.FullName);
You are creating a new instance of the form. I'm assuming your main project is an exe that runs an shows the form. Your second project is then another exe that runs and wants to change the selected item. By creating a new instance of the form you will be changing the selected item on the new form, not the old one.
What you need to do is somehow pass the form object over to the secondary project. possibly some static method that gets a singleton instance of the form maybe.
I'm still not entirely sure why you are using reflection, you could just give the second project a reference to the first.

The first question I'd ask is: why are you using reflection here? Just set the value through the public API. If you are messing underneath the public API, then yes: it is entirely possible that some events won't get fired.
Perhaps if you could show us exactly how you are doing this?

Related

How can I grant focus to a created window instead of creating a new instance?

I found so many topics about how to prevent multiple instances of Windows.Forms but I still can't find how to prevent multiple instances for WPF windows. I'll explain my idea. I have a WPF Window. This window have a beautiful custom button. When the button is clicked it opens new window. My problem is that when I click multiple times on the same button the same window appears as many times I clicked the button. How to prevent this? Is it possible instead a new window is opened simply the already opened one to take the focus?
Well you have to check if it is created before creating a new one:
Pseudo like code (only have notepad here)
private YourWindow wnd = null;
void OnButton_Click()
{
if (wnd == null) wnd = new YourWindow();
wnd.Show();
}
I have seen a few methods and this is the one I use. Its in VB but you should be able to convert it to C#. There might well be better ways but I'm no WPF expert!
I have a function tucked away in a module that looks like this
Public Class FormsCollection
Public Shared Forms As ArrayList = New ArrayList
End Class
Public Function Find_form(strForm_name As String)
For Each F In FormsCollection.Forms
If F.ToString = strForm_name Then
Find_form = F
Exit Function
End If
Next
Find_form = Nothing
End Function
Then when I’m trying to open a form the code looks like this
Dim FormToOpen As FormToOpen
If IsNothing(Find_form("FormToOpen")) Then
FormToOpen = New FormToOpen
Else
FormToOpen = Find_form("FormToOpen ")
End If
With FormToOpen
.Owner = Me
.ShowDialog()
.Activate
End with
I tend to use two approaches. Sometimes, I do as PowerRoy suggests and I store a field in a suitably central place in the application which has a reference to the window. If that field isn't null, I activate it instead of creating a new instance.
Sometimes when there are many types of windows but I only want one of each, I use a list of a common base class (List perhaps). Each created window is put in there, and whenever I want to create or switch to one of them, I filter it by type and check if there's anything there and switch to it if there is. Something like:
List<Window> allWindows = new List<Window>();
// ... elsewhere I want to create a ShinyWindow
void ActivateShinyWindow()
{
var shiny = allWindows.OfType<ShinyWindow>().FirstOrDefault();
if (shiny == null)
{
shiny = new ShinyWindow();
allWindows.Add(shiny);
}
ActivateWindow(shiny);
}
Where ActivateWindow() does whatever is necessary to make it visible and bring it to the front or whatever. Actually the biggest thing I've got doing this is inside a tabbed interface, so it's all run by the enclosing shell window.
This is a bit like Kevin Ross' answer, except I'm indexing the collection by type. It obviously doesn't work if you ever want multiple windows which are instances of the same class, and then you're going to want something more like what Kevin did. My strongly-typed functional-programming background says I'd rather use a nice enum to index the windows than a string though.

C# Null Reference Exception

I am working on the following program which deals with threads and thread priorities.
I have constructed a windows form containing a rich textbox (DisplayTextBox) and two buttons (StartButton for running app and ExitButton for closing app).
In the form, I am creating several threads and running them one after another. The method used by each thread is found in the Threading class. The method in question is PrintOnScreen().
In this method, I am appending the thread name as well as its priority to str of type StringBuilder. Then I want to display the contents of str in DisplayTextBox (which is in Form.cs).
However, I am getting a "NullReferenceException was unhandled: Object reference not set to an instance of an object" error. The line where the error crops up is the following:
DisplayTextBox.Text = Convert.ToString(str);
Can you please help me to solve this error? Thanks.
Edit
Thanks to all for your help. In order to solve the problem, I copied the PrintOnScreen method to the Form.cs class and discarded Threading.cs.
I later used the code given by Anand and placed it below t2.Join(). Now it works like a charm.
The problem occurs in the constructor of your form. You declare DisplayText again as local member, so that the field of your form isn't initialized. Change your constructor like this:
private void Form1_Load(object sender, EventArgs e)
{
DescTextBox.Visible = false;
DisplayTextBox = new RichTextBox();
DisplayTextBox.Location = new Point(15, 31);
DisplayTextBox.Height = 258;
DisplayTextBox.Width = 303;
panel1.Controls.Add(DisplayTextBox);
}
and it should work like you expect.
Edit: But beware of the problems you will get, when you want to change UI elements from a background worker thread. In those cases you will have to use the invoke pattern.
I tried this in simple console application and it worked fine.
The issue is with DisplayTextBox. If you want to interact with any control, then you have to use UI thread or Dispatcher.
Use the following code in your Threading Class,
instead of
DisplayTextBox.Text = Convert.ToString(str);
use this one
Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(
delegate()
{
DisplayTextBox.Text = Convert.ToString(str);
}
));
You cannot communicate with controls from any other thread than main application's thread. You need to use the dispather for this. Have a look here: http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx
EDIT
#Fischermaen - heh, didn't notice this but it still won't work because of the line, where he wrote it fails. He still needs to use dispatcher to set the Text property on the control from the non-main threads
EDIT 2
Related threads:
How to update the GUI from another thread in C#?
In WinForms, why can't you update UI controls from other threads?
Um.
Can't see from here, but part of the reason you are having difficulty is the lack of encapsulation and poor lifetime management in your code.
Instantiate str inside the PrintOnScreen method, give it a better name as well, no appranrent need to be a member variable, no need at all to make it public.
Instead of having a void result, have it return the string result
e.g.
SomeTextBox = PrintOnScreen(); // (GetThreadDetails might be a better name...)
As a tip don't mix presentation and logic. Keep you UI controls thoroughly inside whatever owns them.
And don't do
public SomeType SomeName;
make it a property and give it getter and a setter , even if it's the short form
public SomeType SomeName {get; set;}
Any other bit of code could do something really foolish like
Form1.SomeType = (SomeOtherType)someVar; // with appaling consequences.
Nothing should have more than one owner, any other path leads to ruin.
PS str.ToString() would be a better option than Convert.ToString(str);
Well, this is not very clear for me what you are trying to achieve, however the problem is that the base form Threading class inherits from not being loaded when you are trying to access control on it (window handle still not exists) Also this is the reason you see nothing on Form1 itself, because your threads outputs into hidden form, which is not shown.
I think that you are trying to solve thread access issue, raised by SOReader. This is not proper way to do this.

C# Trigger a method after another method (defined in a third party dll) is completed

This may fall into the category of method extending, overriding or polymorphism (I'm new to C# and OO so forgive me, I'm still learning :-) ).
I have an app that is utilizing a 3rd party API. Within the API there is a method for right click+select action on a custom control (the control is an image viewer where a user can right click and cycle to another image that exists within the parent group).
In my limited understanding I would think one of these 2 things would need to happen (whether either one can be done or whether either one is a good solution is up in the air!)
I don't want to override the existing method, I just want to append to it somehow.
If there was a way I could detect when the specific event was triggered and completed, then call my method. Set up some kind of listener if thats available.
Thanks!!
As you didn't post any reference, I'll try to outline some ways.
if there is an event
CustomControl cc = yourCustomControl;
cc.SelectionCompleted += (sender, args) => { YourMethod() };
This is using an anomynous event handler using a lambda.
Another way would be:
public class Form1 : Form
{
public Form1()
{
this.cc.SelectionCompleted += HandlerSelectionCompleted;
}
public void HandlerSelectionCompleted(object sender, EventArgs e)
{
YourCustomMethod();
}
}
there is a method to override
public class YourCustomControl : CustomControl
{
public override void Selection()
{
base.Selection(); // first call the original method
// now do some custom stuff
}
}
You can not override that method: that's right, if it's not protected/virtual/abstract whatever, or if you can not derive from that component's class.
You can search the component for the events and guess (if there is no any documentation) which event is fired after your desired action. And actually execute the code in that event handle.
There could be other "hacking" tricks, but I personally would avoid to do something like that, if not for personal passion, but focus on reachitecturing my program, in order to fit the requirements and support that component, as much as I can.
Regards.
What you are describing is a tenant of Aspect Oriented Programming AOP. If you want to instrument a 3rd party .NET dll, I would recommend PostSharp http://www.sharpcrafters.com/solutions/logging

what WPF method can I use to set some properties on a control's first display?

I need to store my app window's size/position and state when the user closes the app and set them back when the user thereafter opens the app.
I did this easily using registry keys (is this even the best way to do?), but I'm wondering where I actually should put the code to set those properties.
I need to set them when the window first "appears" I think. But I have several methods that could be used in this case, namely:
Window.Show()
Window.Activate()
Window.ApplyTemplate()
Window.Arrange()
Window.ArrangeCore()
Window.ArrangeOverride()
Window.BeginInit()
Window.EndInit()
Window.Measure()
Window.MeasureCore()
Window.MeasureOverride()
Window.OnApplyTemplate()
Window.OnInitialized()
Window.OnRender()
Window.UpdateLayout()
I'm aware that most of them just are a bad idea (UpdateLayout() will be called waaaaaaay too often for instance). Idealy I'm looking for a method that will only be called once in the window's life so that I don't have to add a flag checking if this is the method's first call.
so which one would be the best in this case? and why?
side question: I put the code to save the values in Window.Close() (I'm overriding the method in my MyWindow class), But I could as well have put it in Window.OnClosing() or Window.OnClosed(). Does this make any difference in my case?
side question (bis): I also have to save a datagrid's column order, where should I put both "saving" and "loading" code in this case?
Ok, it seems to me you are treating WPF like you would an old-school WinForms application. You no longer need to monitor form events to retrieve information from the Forms Properties. A majority of WPF Control properties are something known as a Dependency Property.
Amonst some of the clever things dependency properties introduce is Data Binding.
If you then consider writing the application with an MVVM Architecture you will quickly be able to work the following out yourself... =)
In the View*1, you can create either Dependency Properties, or standard properties and implement INotifyPropertyChanged, which hold the Size/Layout/Position/etc. Then bind the form's properties (in xaml or code) to the View's Properties. You can then implement any functionality you like for storing/retrieving the defaults and have automatic updates when the form is changed by simply adapting the Get/Set of the properties in the view.
As a quick example on the Windows' Title:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding Path=DisplayName}"
WindowStartupLocation="CenterScreen" >
<Grid>...</Grid>
</Window>
An example implementation of the view:
public class SampleView : System.ComponentModel.INotifyPropertyChanged
{
public event PropertyChangedEventHandler System.ComponentModel.INotifyPropertyChanged.PropertyChanged;
public delegate void PropertyChangedEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e);
private string _Title;
public string Title {
get {
if (_Title == null) {
_Title = My.Settings.MainWindowTitle;
}
return _Title;
}
set {
_Title = value;
if (!(_Title == My.Settings.MainWindowTitle)) {
if (PropertyChanged != null) {
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Title"));
}
My.Settings.MainWindowTitle = Title;
My.Settings.Save();
}
}
}
}
EDIT: Regarding how best to store user preferences, I wouldn't recommend the registry though, it's far from unheard of. The registry nowadays is packed full of settings that, in my opinion, the registry wasn't really designed for. Consider using application settings set to a user scope. That will handle most of the subleties of where and how the data is stored/retrieved and provide a nice type safe interface for you.
*1 I personally prefer to try and bind everything to the ViewModel and have almost totally dumb Views; though I do know there are plenty of valid cases for the Views having code. I wouldn't say the Size/Layout/etc is really a Business Logic Concern and isn't something I've concerned myself with up to now, so this should probably be handled in the View itself.
EDIT 2 - A quick example of User/Application scope settings:
Here is a quick picture of the settings I added to the project:
The following code attempts to use both the application and user scoped settings.
NB: Application Scope Settings are ReadOnly at runtime
public class SettingsExample
{
private Form1 frmMain = new Form1();
public void Main()
{
frmMain.BackColor = My.Settings.DefaultBackColour;
}
public void UserLoggedIn()
{
frmMain.BackColor = My.Settings.UserBackcolour;
}
public void UpdateUserBackcolour(System.Drawing.Color newColour)
{
My.Settings.UserBackcolour = newColour;
My.Settings.Save();
}
public void UpdateDefaultBackcolour(System.Drawing.Color newColour)
{
My.Settings.DefaultBackColour = newColour;
// Compiler Error
// This property is read only because it is an application setting
// Only user settings can be changed at runtime
}
}
First off, you forgot about
Loaded event - occurs when the element
is laid out, rendered, and ready for
interaction. (Inherited from
FrameworkElement.)
There is no one simple answer. Scenario may vary whether it'a child "dialog-like" window (then I would just set the size a line before Show() ), a new instance of the same window or a new instance of the app.
I will argue that UpdateLayout() is a bad idea. Actually, it's a very good idea. For example:
private bool m_onStart = true;
public MainWindow()
{
InitializeComponent();
this.LayoutUpdated += new EventHandler(MainWindow_LayoutUpdated);
}
void MainWindow_LayoutUpdated(object sender, EventArgs e)
{
if (m_onStart)
{
m_onStart = false;
Dispatcher.BeginInvoke(() =>
{
//Start App
}
);
}
}
Even if it's called a thousand time per second (which is very unlikely) you won't even notice it and won't hurt the performance.
All in all, you can make a helper method that saves user preference and second the reads it. Since the task is view related and using MVVM and binding is an overkill for this, set the size in Loaded event (do it when all ctors, initialization and visual tree is done).
My Choice: I finally ended up putting the code to load the values from the registry in window.Show().
the reason I did this is because of 2 things:
I store the state of the window, (minimized/maximized) and the way WPF does it, I need to first set the width/height, then the maximized state (if needed), otherwise it messes up the layout. And if I don't set the width/height first, I loose them when I de-maximize the window thereafter. So I have to do things in this order precisely: Width + height and them state. (Also, this is necessary when working with multiple screens, otherwise you loose the screen you were working on). This means that some of the methods above are impractical (the "measure" ones for instance)
adding to this, if I put my code in most of the methods above-mentioned, I'll get a bad looking effect on first display: the window will first appear with its height and width set, in the middle of the screen, and then after a small delay, the window gets maximized.
putting the code in window.Show() managed to solve those 2 issues. I might have had the same result with one or more of the other methods, but I simply got fed-up with trying different configurations and ended up using the first one that gave me entire satisfaction.

How to have code in the constructor that will NOT be executed at design time by Visual Studio?

I have a method call in the constructor of my user control that does something that won't work at design time (connecting to a database), and Visual Studio just bailed out when I tried to add that control to the GUI designer.
Sure, I can factor out that code to a separate method, but I don't like the idea that every time I use that object I need to remember to execute a certain method which is essential to that object's function (that's what the constructor is for!).
Is there something like a preprocessor symbol that I can mark my code with so that Visual Studio won't try to execute that code at design time?
As others have stated, you can use the DesignMode property of the Component class. However, you will not be able to do this in the constructor of your control. The DesignMode property is always false in the constructor and methods called by the constructor. To get around this, re-factor your code to connect to the database in the OnLoad() callback. The DesignMode property is valid at that point. See here for the reasoning (look for the DesignMode section of the article).
I just ran across this blog entry that describes how to use the System.ComponentModel.LicenseManager.UsageMode property for doing the same thing. The blog describes an additional shortcoming of the DesignMode property when dealing with nested controls. Apparently, the UsageMode property doesn't have the same shortcomings and is available for use in the constructor. I cannot personally vouch for it, but might be worthwhile looking into.
In Windows Forms?
if (!DesignMode)
{
// code that shouldn't be executed at design time
}
As others have mentioned, this won't work in the constructor. It's often used in the Form.Load event.
Have a look at this
Component.DesignMode Property
I liked Michael Petrotta's approach for Windows Forms. If anyone wants to apply the same technique to WPF, simply use IsInDesignMode.
Example:
public SomeViewModel()
{
if (!IsInDesignMode)
{
DoWork();
}
}
public SomeViewModel()
{
if (!IsInDesignMode)
{
DoWork();
}
}
This code above if you are working on the actual UI that you are trying to work on. In a situation that you have something like this on a control, when you switch back to the designer for that control it's ok and no design time error. Now if you added that control that contains the code above to some other Form or another control via dragging it from the toolbox, it will show some design time errors.
This is the only code that worked for me, using WPF UserControl on a Windows Form.
private bool? inDesignMode;
public bool IsDesignMode
{
get
{
if (inDesignMode == null)
{
var prop = System.ComponentModel.DesignerProperties.IsInDesignModeProperty;
inDesignMode = (bool)System.ComponentModel.DependencyPropertyDescriptor
.FromProperty(prop, typeof(FrameworkElement))
.Metadata.DefaultValue;
if (!inDesignMode.GetValueOrDefault(false) && System.Diagnostics.Process.GetCurrentProcess().ProcessName.StartsWith("devenv", StringComparison.Ordinal))
inDesignMode = true;
}
return inDesignMode.GetValueOrDefault(false);
}
}

Categories

Resources