I need some help regarding a driver I`m building. I have a structure of some data in my static class. The data of this structure object has to be manipulated from outside my driver class. Into my class I have to prepare some textBoxes, which can be assigned and used from outside the class. Each structure value becomes one textBox. Now my problem is, I have to connect this dynamic changable structure values with the corresponding textBox. I have to use dataBinding, cause there will be a huge amount of data I have to use.
Pls check out the following code snippet for understanding:
public static class driver
{
#region " data preparation "
//structure definition
public struct _data
{
public string moduleName;
public string dynamicNumber1;
//...
}
//instance object of struct
private _data moduleData = new _data();
//get;set property
public _data pModuleData
{
get
{
return moduleData;
}
set
{
moduleData = value;
}
}
#endregion
//build data binding(s) for each single "moduleData.structureItem"
//???????????????????? moduleData_itemBinding_ModuleName
//???????????????????? moduleData_itemBinding_dynamicNumber1
//...
#region " form elements preparation for external assignments "
//instance of forms objects, data can be assigned and used outside of this public static class
public static System.Windows.Forms.TextBox textBox_ModuleName = new System.Windows.Forms.TextBox();
public static System.Windows.Forms.TextBox textBox_dynamicNumber1 = new System.Windows.Forms.TextBox();
#endregion
#region " class initialisation "
static driver()
{
// class initialisation part
textBox_ModuleName.DataBindings = moduleData_itemBinding_ModuleName; //assign databindings from above ???????????
textBox_ModuleName.DataBindings = moduleData_itemBinding_dynamicNumber1; //adding databindings from above ???????????
}
#endregion
}
Thanks for help!
KISS.
I think it is possible to make as follows. Define your class:
public class Driver
{
public Driver(TextBox moduleName, TextBox dynamicNumber)
{
textBox_ModuleName = moduleName;
textBox_DynamicNumber = dynamicNumber;
textBox_ModuleName.DataBindings.Add("Text", this, "ModuleName");
textBox_DynamicNumber.DataBindings.Add("Text", this, "DynamicNumber");
}
public string ModuleName { get; set; }
public string DynamicNumber { get; set; }
private TextBox textBox_ModuleName;
private TextBox textBox_DynamicNumber;
}
Then create textboxes on the form:
var textBox1 = new TextBox { Parent = this };
var textBox2 = new TextBox { Parent = this, Top = 30 };
Create instance of your class and pass to it these textboxes:
var driver = new Driver(textBox1, textBox2);
driver.ModuleName = "foo";
driver.DynamicNumber = "bar";
// data will be appear in the textboxes
It works.
Related
I have a WPF Project where I want to save DataRows from a DataGrid into an "options" class and retrieve those variables in another window.
Thats how I save my Variable from my DataGrid into my "options" Class (mainWindow.xaml.cs):
options.title = Convert.ToString((showEntries.SelectedItem as DataRowView).Row["title"]);
This Variable im saving via a getter and setter (options.cs):
public string Title
{
get { return title; }
set { title = value; }
}
And now I want to retrieve the saved variable in another window(updateDatabse.xaml):
private void getUpdateEntries()
{
Options returnValues = new Options();
titleBox.Text = returnValues.Title;
}
My Question is: Why is my textbox "titleBox" empty when running my code.
If the logic of your task does not provide for the creation of several instances of classes (and as far as I understand your explanations, this is so), then you can use the Singlton implementation.
Example:
public class Options
{
private string title;
public string Title
{
get { return title; }
set { title = value; }
}
private Options() { }
public static Options Instance { get; } = new Options();
}
Options.Instance.Title = Convert.ToString((showEntries.SelectedItem as DataRowView).Row["title"]);
private void getUpdateEntries()
{
titleBox.Text = Options.Instance.Title;
}
You mixed things up.
private void getUpdateEntries()
{
Options returnValues = new Options();
returnValues.title = Convert.ToString((showEntries.SelectedItem as DataRowView).Row["title"]);
titleBox.Text = returnValues.Title;
}
this might be a very basic question but I am cracking my head at this since months.
I want to create a simple UI for creating objects of the class I pass into the UI constructor.
Let say I have 2 classes:
class Test1
{
public static List<Test1> objectList;
public string code;
public string name;
}
class Test2
{
public static List<Test2> objectList;
public string code;
public string name;
public int value;
}
(the static classes would contain all the objects created out of that class)
what I would like to do is to is to create a Code which takes a class as a variable (maybe a generic class?) and based on that creates all the labels and textboxes based on the fields available in the class.
e.g.
public RegisterUI<T> ()
{
Grid grd = new Grid();
DataGrid dg = new DataGrid();
Button saveBtn = new Button();
//Binding the static list of objects to the DataGrid
dg.ItemSource = T.objectList;
//Adding the UI elemnts to the grid
grd.children.add(dg);
grd.children.add(saveBtn);
//Creating for each field in the Class T a lable based on its name and a combobox + binding
foreach(field in T)
{
Lable lbl = new Lable(field.getName);
ComboBox cbx = new ComboBox();
grd.children.add(lbl);
grd.children.add(cbx);
}
}
Is this even possible? I hope I was not to vague with the mockup code, and you can understand what I am heading for.
Any advice would be highly appreciated. Thanks a lot :)
Yes, it's possible. I've done this exact thing for the purpose of automatically creating settings dialogs (I got tired of making a custom form anytime one of my programs had settings that needed modified by the user).
How?
You're going to need to look into "reflection" which provides you a way to interrogate the structure of objects dynamically.
I don't use generics for this, but rather interrogate the Type from within the class.
If I pass in Test1 into my class I get this:
I wish I could supply source code, but alas, it belongs to my employer. I can, however, supply a short snippet to get you started:
Type type = typeof(Test1);
//Get public fields
List<FieldInfo> fieldInfo = type.GetFields().ToList();
//Get private fields. Ensure they are not a backing field.
IEnumerable<FieldInfo> privateFieldInfo = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(f => !f.Name.Contains("k__BackingField"));
//Get public properties
List<PropertyInfo> properties = type.GetProperties().ToList();
//Get private properties
properties.AddRange(type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance));
Hmm, looks like something an old demo might help solve:
Note: I'm using JSONs and NewtonSoft's JSON library for my implementation to read a JSON and build the object / UI from that:
private void LoadConfig()
{
JsonSerializerSettings jss = new JsonSerializerSettings()
{
DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate
};
var cfg = ConfigIO.OpenDefault();
ConfigItem ci = JsonConvert.DeserializeObject<ConfigItem>(cfg.Object);
IEnumerable<MemberInfo> atts = ConfigInterOps.GetAttributes(typeof(ConfigItem));
FillForm(ci, atts);
}
private void FillForm(Object referenceObject, IEnumerable<MemberInfo> atts)
{
int location = 5;
foreach (var att in atts)
{
var cfg = new ConfigurationBox(att.Name, referenceObject.GetType()
.GetProperty(att.Name).GetValue(referenceObject, null));
cfg.Name = $"cfg_ {att.Name}";
cfg.Top = 3 * location;
location += 10;
Controls["flowLayoutPanel1"].Controls.Add(cfg);
}
}
A couple classes I made and use that are referenced above:
public static class ConfigInterOps
{
public static IEnumerable<MemberInfo> GetAttributes(Type type)
{
return type.GetMembers()
.Where(x => x.MemberType == MemberTypes.Property ||
x.MemberType == MemberTypes.Field);
}
}
public static class ConfigIO
{
public static void Save(Config cfg)
{
UseDefaultLocation(cfg);
if (!File.Exists(cfg.FileLocation))
{
File.Create(cfg.FileLocation);
}
File.WriteAllText(cfg.FileLocation, JsonConvert.SerializeObject(cfg));
}
private static void UseDefaultLocation(Config cfg)
{
cfg.FileLocation = cfg.FileLocation ?? Path.Combine($"{AppContext.BaseDirectory}", "conf.jobj");
}
public static Config OpenDefault()
{
var cfg = new Config();
UseDefaultLocation(cfg);
return Open(cfg);
}
public static Config Open(Config config)
{
var text = File.ReadAllText(config.FileLocation);
Config openedCfg = JsonConvert.DeserializeObject<Config>(text);
return openedCfg;
}
}
the reference to ConfigurationBox is a custom control:
And after the config is loaded it looks like:
Obviously it is rough, but it should provide all the basics you need to do something similar.
Dunno if I'm going the right way about this? The contents of the structure below is defined elsewhere. when I run the code it is just outputting a list of 4 zeros. any help would be greatly appreciated.....
public class NativeMethods
{
public struct FT_DEVICE_LIST_INFO_NODE
{
public uint ID;
public uint LocId;
public string SerialNumber;
public string Description;
}
[DllImportAttribute(#"C:\Users\Brendan\Documents\libMPSSE.dll", EntryPoint = "SPI_GetNumChannels")]
public static extern uint SPI_GetChannelInfo(uint index, ref FT_DEVICE_LIST_INFO_NODE chanInfo);
}
public partial class Form1 : Form
{
List<uint> items = new List<uint>();
public Form1()
{
InitializeComponent();
NativeMethods.FT_DEVICE_LIST_INFO_NODE devlist = new NativeMethods.FT_DEVICE_LIST_INFO_NODE();
for(uint x=0;x<4;x++)
{
index = 0;
items.Add(NativeMethods.SPI_GetChannelInfo(index, ref devlist));
}
listBox.DataSource = items;
}
}
Since you wrote that your structure is defined elsewhere I asume you can't change it.
The usual way to get a custom made display string is to wrap your structure in a minimal class, maybe like this:
class FT_DEVICE_wrapper
{
public FT_DEVICE_LIST_INFO_NODE INFO_NODE { get; set; }
public FT_DEVICE_wrapper(FT_DEVICE_LIST_INFO_NODE data_)
{ INFO_NODE = data_; }
public override string ToString()
{
return string.Format("ID = {0} LocID = {1} SNr = {2} ({3}) ",
INFO_NODE.ID, INFO_NODE.LocId, INFO_NODE.SerialNumber, INFO_NODE.Description);
}
}
Now you can add instances of the wrapper like this:
private void button1_Click(object sender, EventArgs e)
{
FT_DEVICE_LIST_INFO_NODE N1 = new FT_DEVICE_LIST_INFO_NODE();
N1.ID = 1;
N1.LocId = 1001;
N1.SerialNumber = "123-456-00";
N1.Description = "test 01";
FT_DEVICE_wrapper W1 = new FT_DEVICE_wrapper(N1);
listBox1.Items.Add(W1);
}
As you can see the structure's data are displayed in whichever way you format the output string.
And you can access the structure by casting the Items like this
Console.WriteLine( ((FT_DEVICE_wrapper) listBox1.Items[0]).INFO_NODE.Description );
Or, imo a little better like this:
FT_DEVICE_LIST_INFO_NODE node = ((FT_DEVICE_wrapper)listBox1.Items[0]).INFO_NODE;
Console.WriteLine(node.SerialNumber);
You may want to consider looking into ListViews, which support columns; here the way to add the structure would be quite different as you would want to put some of the date fields into separate columns.
If you want to use DataBinding you start by creating a proper List:
List<FT_DEVICE_wrapper> items = new List<FT_DEVICE_wrapper>();
and then replace
listBox1.Items.Add(W1);
by
items.Add(W1);
listBox1.DataSource = items;
Note: By simply adding a ToString method to the original structure you cold also make the structure display fine in the ListBox without being wrapped..
I want to retrieve data from a list I created that contains class objects via a foreach but I'm not able to.
Can somebody please tell me what's missing in my code?
I have a class Recipes.cs that contains the following code:
public class Recipe
{
string _oveskrift;
int _recipe_id;
string _opskrift;
int _kcal;
public Recipe(string overskrift, int recipe_id, string opskrift,int kcal)
{
_oveskrift = overskrift;
_recipe_id = recipe_id;
_opskrift = opskrift;
_kcal = kcal;
}
}
public class Recipes
{
public List<Recipe> CreateRecipeList()
{
Recipe opskrift1 = new Recipe("Cornflakes med Chili",1,"4 kg cornflakes bages", 420);
Recipe opskrift2 = new Recipe("Oksemørbrad",2,"Oksemørbrad steges i baconfedt", 680);
Recipe opskrift3 = new Recipe("Tun i vand",3,"Dåsen åbnes og tunen spises", 120);
List<Recipe> Recipelist = new List<Recipe>();
Recipelist.Add(opskrift1);
Recipelist.Add(opskrift2);
Recipelist.Add(opskrift3);
return Recipelist;
}
}
I call CreateRecipeList() from another class calculator.cs and the code looks like this:
private int FindRecipes()
{
List<Recipe> Rlist = new List<Recipe>();
// CREATE THE CLASS AND ADD DATA TO THE LIST
Recipes r = new Recipes();
Rlist = r.CreateRecipeList();
int test = 0; // used only for test purposes
foreach(var rec in Rlist)
{
rec.????
test++;
}
return test;
}
I would presume that I should be able to dot my way into rec."the class object name"."the value"
But nothing happens!.
All I get is the option to rec.Equals, rec.GetHashcod ect. which is clearly wrong.
For the record I have also tried:
foreach(Recipe rec in Rlist)
{
rec.????
test++;
}
But that doesn't work either.
The Int test are only there for test purposes.. and it return 3.. so the list does contain the correct information.
Please show us the code for the Recipe class. Besides that, you're most of the way there...
foreach(Recipe rec in Rlist)
{
string str = rec.<PropertyName>;
}
You need to set the proper access modifiers for the members in your Recipe class.
public : Access is not restricted.
protected : Access is limited to the containing class or types derived from the containing class.
Internal : Access is limited to the current assembly.
protected internal: Access is limited to the current assembly or types derived from the containing class.
private : Access is limited to the containing type.
By default, the members of your Recipe class will have the private access modifier.
string _oveskrift;
int _recipe_id;
string _opskrift;
int _kcal;
is:
private string _oveskrift;
private int _recipe_id;
private string _opskrift;
private int _kcal;
Maybe you want to modify your member access as follows, in order to set the values of the members only inside the class code. Any attempt to set their values outside the Recipe class will fail, as the set is private. The get remains public, which makes the value available for reading.
public class Recipe
{
string _oveskrift;
int _recipe_id;
string _opskrift;
int _kcal;
public string Oveskrift
{
get
{
return _oveskrift;
}
private set
{
_oveskrift=value;
}
}
public int RecipeId
{
get
{
return _recipe_id;
}
private set
{
_recipe_id = value;
}
}
public string Opskrift
{
get
{
return _opskrift;
}
private set
{
_opskrift = value;
}
}
public int Kcal
{
get
{
return _kcal;
}
private set
{
_kcal = value;
}
}
public Recipe(string overskrift, int recipe_id, string opskrift, int kcal)
{
_oveskrift = overskrift;
_recipe_id = recipe_id;
_opskrift = opskrift;
_kcal = kcal;
}
}
Also, please read as soon as possible the following MSDN article: Capitalization Conventions. And also, this one: C# Coding Conventions (C# Programming Guide).
This should be easy. I want to populate a grid with a custom data source at runtime. For some reason, it simply does not work.
Running via a unit test
[TestMethod]
public void Runtest() {
TestForm form = new TestForm();
TestControl control = new TestControl();
form.Controls.Add(control);
control.LoadData();
form.ShowDialog();
}
The relevant Control code
public void LoadData() {
SourceRecord[] original = new SourceRecord[] {
new SourceRecord("1"), new SourceRecord("3"), new SourceRecord("9") };
gridControl1.DataSource = original;
GridColumn col = gridView1.Columns.AddVisible("SomeColumn");
col.FieldName = "SomeName";
//gridControl1.ForceInitialize();
}
Record info
public class SourceRecord {
public string SomeName = "";
public SourceRecord(string Name) {
this.SomeName = Name;
}
}
I end up with some column just called "Column" which displays 3 rows reading ClassLibrary1.SourceRecord. Then my custom column "Some Name" has no data. According to the devexpress walkthrough I only need to populate the DataSource with a class that implements IList, which I did with an Array.
How can I display just my custom column and give it the data?
The grid control will bind columns to properties only. Try this:
public class SourceRecord
{
public string SomeName { get; set; }
public SourceRecord(string Name)
{
SomeName = Name;
}
}
public void LoadData()
{
SourceRecord[] original = new SourceRecord[] { new SourceRecord("1"), new SourceRecord("3"), new SourceRecord("9") };
GridColumn col = gridView1.Columns.AddVisible("SomeColumn");
col.FieldName = "SomeName";
gridControl1.DataSource = original;
}