I want to refactor some of my code, so I would like to create method for few repeating tasks. One of methods, depending on context, include working something with properties. Most of properties are string, but there are also enum and int types.
For example, method should look like this:
private void someMethod (int i, 'here should be property') {
//enter code here
}
So, does anybody know how to pass this properties?
Thanks in advance!
Another explanation. This code should change label properties: text, font... But, label.Text should be changed depending on entry parameter.
it should look like this
private void setLabel (Label label, 'I dont know what goes here to pass a property') {
label.Text = user.'property'.toString();
//some more code
}
If you don't have any particular reason why you want to actually pass the property, you can just pass the value of that property:
private void setLabel (Label label, object propertyValue)
{
label.Text = propertyValue.ToString();
}
And then call it like:
setLabel(myLabel, user.ThePropertyIWant);
You should be able to do such thing with reflection:
http://www.dotnetperls.com/reflection-field
Related
I'm creating Library app using WinForms.
I have eLibraryClasses where I have all data including each form services, and eLibraryUI where I have all my WinForms.
I have a problem in one form where I would like to change states of button.Visible to false or true.
I tried to extract method from UI to Service like:
public void ShowDrawnBook(bool clickedButtonVisible, bool toReadButtonVisible, int buttonNumber)
{
//Hide button which cover answer
clickedButtonVisible = false;
//Add option to add randomized book to "To read" bookshelf
toReadButtonVisible = true;
//Return index of clicked button
buttonClicked = buttonNumber;
}
And UI looks like for example:
service.ShowDrawnBook(randomBook2Button.Visible, toReadButton.Visible, 2);
I tried, but I couldn't use "ref" neither "out" for this properties.
And in this way above it's building properly, but not working because of not changing parameters out of method.
I have such a many of them in this form, so I could do it like
randomBook2Button.Visible = SomeMethod();
toReadButton.Visible = SomeMethod();
... for every variable
But I would like to avoid it.
Is there any way to send there buttons properties (bools) as parameters?
Booleans are passed by value, not reference, thus your "problem".
To solve your problem, just take the Button(s) as parameters instead of the booleans. Button is a class, thus is passed by reference.
Then in your method change the state of the Button(s) properties as you see fit.
public void MyMethod(Button myButton1, Button myButton2)
{
myButton1.Visible = true;
myButton2.Visible = false;
}
I have a WPF MainWindow Form with a ListBox and a TextBox that looks like this:
Figure A. WPF MainWindow with Sample Text.
Now, the Load Assembly... OnClick button event allows me to select a .NET Assembly and load it up using DnLib
Then, if I want to display the Methods bodies I would do it like so:
Assembly asm = Assembly.LoadFile(filename);
foreach (Module mod in asm.GetModules())
{
foreach (Type types in mod.GetTypes())
{
foreach (MethodInfo mdInfo in types.GetMethods())
{
listBox.Items.Add(mdInfo.Name);
}
}
}
This adds each found Method name to the ListBox on the left, resulting like so:
Figure B. Showing the ListBox Filled with Methods Names
Now the trick part, I would like to for whichever method I select from the ListBox to display its respective MethodBody IL on the TextBox
How can I achieve such thing?
«Phew!» Finally Solved it!
Here's the solution for whoever tries to do the same thing in the future.
Make an instance of 'List' and then iterate through the methods and assign the names to such list, then whenever your SelectedItem index value changes, I can simply call GetMethodBodyByName and then I can surely solve this issue
Here's how to implement the function GetMethodBodyByName:
public string GetMethodBodyByName(string methodName)
{
ModuleDefMD md = ModuleDefMD.Load(filename);
foreach (TypeDef type in md.Types)
{
foreach (MethodDef method in type.Methods)
{
for (int i = 0; i < type.Methods.Count; i++)
{
if (method.HasBody)
{
if (method.Name == methodName)
{
var instr = method.Body.Instructions;
return String.Join("\r\n", instr);
}
}
}
}
}
return "";
}
The idea is that 'GetMethodBodyByName' will receive the method name as a parameter, then it will iterate through methods and see if a method matches the given name, then if found, the function will just simply iterate through that method and output the method's body.
Here's how my ListBox_SelectedItemChanged event looks like:
private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
textBox.Text = "";
textBox.Text = GetMethodBodyByName(method[listBox.SelectedIndex].Name);
}
That's All Folks!
Note: Be careful when doing this approach as if when you request names, different methods can have the same names. But that's a cake for another day, I'm done for now! take care bye-bye!
Working our way up for the Ultimate Solution!
The WPF MainWindow Forms carry with themselves two little useful properties, they are: Tag and Content, the idea is the following one:
With the Tag and Content Property we can assign any values to it that later it can be retrieved On-The-Fly without having to depend on Methods names specifically for this task.
So you would instead of looping each method and get its name respectively you can just do the way I did:
Iterate through the Method, and assign its body to the Tag property, and its name to the Content property, as this last property is the one that handles the actual Title property, so disregarding anything you do with the method in the future and even if it had the same name of another one, it will work no matter what.
How Can We Implement It?
Simply:
<...>
// Inside Method Body iteration routine...
<...>
var instr = mdInfo.Body.Instructions;
// Allocate in a new `ListBoxItem` each method and add it to the current listbox with their
// ... respective Tag and Content information... // Many Thanks Kao :D
newItem = new ListBoxItem();
newItem.Content = mdInfo.Name;
newItem.Tag = string.Join("\r\n", instr);
method.Add(mdInfo);
listBox.Items.Add(newItem);
Then on your SelectedItem Index-Value-Changed Event put this:
MSILTextBox.Clear();
// Retrieve them given the selected index...
// ... the returned value will be the Tag content of the ...
// ... previously saved item.
string getTag= ((ListBoxItem)listBox.SelectedItem).Tag.ToString();
MSILTextBox.Text = getTag;
I see here lot of similar question, but I still not find answer that help me in situation.
I have two frame(lets say FrameChild), one is "in" another(practically FrameChild is in this frame, lets say FrameMain).
When I insert all parameters in FrameChild and tap on button witch is on bottom of FrameMain I call method that return string...
Now when i get string i need to change textbox text in FrameChild
I have tray many way.
First idea was something like:
FrameChild frm = new FrameChild;
frm.textbox.text = "somestring";
But nothing happen.
Than i thing use some property.
in FrameChield:
public string setTicNo
{
set
{
textBox.Text = value;
}
}
in FrameMain:
FrameChild frm = new FrameChild;
frm.setTicNo = "somestring";
When i debbuging I get value, but textbox still is empty...
On the end I try to bind textbox text on setTicNo;
public string setTicNo
{
get
{
return setTicNo;
}
set
{
setTicNo = value;
}
}
Xaml:
Text = {Binding setTicNo, Mode=TwoWay,UpdateSourceTrigger=Explicit}
(here i try use more bindings, but every time i get infinite loop.
Please help , I not have more ideas..
Thanx
Did you try building a single view model and bind it to both frames, if it was passed by ref which is the default it will change the value once you do.
A side note implement a INOTIFYPROPERTYCGANGED in the View model
I am currenly writing a library that allows my to customize form elements. The code below is a function that gets the name of a control, gets the name of the property and then sets the property of the control but I cant seem to get it to work for some reason. Thanks any help is appricated.
The code:
public void SetProp(string name, string prop, string value)
{
Form FormControl = Application.OpenForms[form];
Control mycontrol = FormControl.Controls.Find(name, true)[0];
PropertyInfo pInfo = mycontrol.GetType().GetProperty(prop);
TypeConverter tc = TypeDescriptor.GetConverter(pInfo.PropertyType);
var x = tc.ConvertFromString(value);
pInfo.SetValue(name, x, null);
}
Sample Call:
SetProp("greg", "Text", "hi")
You need to pass in the actual source object into the PropertyInfo.SetValue call so it can actually be modified. PropertyInfo is basically just information about the property (hence the name), it has no attachment to that specific instance.
You can get it work by changing your call like so:
pInfo.SetValue(mycontrol, x);
http://msdn.microsoft.com/en-us/library/hh194291(v=vs.110).aspx
I am trying to write a function as follows:
private void Func1(DataColumnChangeEventArgs e)
{
ds.TableName.AddRow(
e.Row[e.Column.ColumnName, DataRowVersion.Original].ToString(),
e.Row[e.Column.ColumnName, DataRowVersion.Proposed].ToString());
}
and I am calling it as:
private void Func2()
{
DataColumnChangeEventArgs e = new DataColumnChangeEventArgs(
dataTable.Rows[index],
dataTable.Columns["ColName"],
newValue);
e.ProposedValue = newValue;
Func1(e);
}
However, e.Row[e.Column.ColumnName, DataRowVersion.Proposed].ToString() is throwing a VersionNotFoundException. Is there any way to achieve this?
I would say, your method should look like this:
ds.TableName.AddRow(e.Row[e.Column.ColumnName].ToString(), e.ProposedValue.ToString());
As there is no versions in that row in your row in args, but there is new and old values...
DataColumnChangedEventArgs is designed to be used with a class like DataTable. The DataTable creates an instance when calling the associated events (like ColumnChanged). Creating an instance of one will not actually create the change to the data row.
The e.ProposedValue = newValue is redundant, you already gave the newValue in the constructor.
You can access the value through e.ProposedValue. So through this system you can only make one change to the row at a time and you must remember which column it was.