How to bind an advBandedGridView at run time? - c#

I am new in the using of DevExpress. I need to design and bind a complex DataGrid.
I have designed it using the Designer. The datagrid is of type Master-Detail, and it contains the 'MainGrid' and other detail grids. One of them is of type: 'advBandedGridView'
The design of the MainGrid is as shown below:
And the design of the 'advBandedGridView' is as follows:
Now, I need to fill my DataGrid using Lists collections, so I used the following Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
ArrayList a = new ArrayList();
Term_Space_Grid t = new Term_Space_Grid("x", "y", true, "z");
t.expansions = new List<MyExpansions>();
t.expansions.Add(new MyExpansions(0, "Aya", 0, 0, 0, 0, 0));
a.Add(t);
resultsGridControl.DataSource = a;
}
}
public class Term_Space_Grid
{
public string x { get; set; }
public string y { get; set; }
public string g { get; set; }
public bool z { get; set; }
public List<MyExpansions> expansions { get; set; }
public Term_Space_Grid(string x, string y, bool z, string g)
{
this.x = x;
this.y = y;
this.z = z;
this.g = g;
}
}
public class MyExpansions
{
public Morphos morphos { get; set; }
public Semantics semantics { get; set; }
public MyExpansions(int morphoID, string morphoDerivation, int synID, int subID, int supID, int hasID, int insID)
{
this.morphos = new Morphos(morphoID, morphoDerivation);
this.semantics = new Semantics(synID, subID, supID, hasID, insID);
}
}
public class Morphos
{
//public List<Morph> morph{ get; set; }
public Morph morph { get; set; }
public Morphos(int morphoID, string morphoDerivation)
{
//this.morph = new List<Morph>();
//this.morph.Add(new Morph(morphoID, morphoDerivation));
this.morph = new Morph(morphoID, morphoDerivation);
}
}
public class Semantics
{
public List<Sem> synonyms { get; set; }
public List<Sem> subClasses { get; set; }
public List<Sem> superClasses { get; set; }
public List<Sem> hasInstances { get; set; }
public List<Sem> instanceOf { get; set; }
public Semantics(int id1,int id2, int id3, int id4, int id5 )
{
this.synonyms = new List<Sem>();
this.subClasses = new List<Sem>();
this.superClasses = new List<Sem>();
this.hasInstances = new List<Sem>();
this.instanceOf = new List<Sem>();
this.synonyms.Add(new Sem(id1));
this.subClasses.Add(new Sem(id2));
this.superClasses.Add(new Sem(id3));
this.hasInstances.Add(new Sem(id4));
this.instanceOf.Add(new Sem(id5));
}
}
public class Morph
{
public int MorphoID { get; set; }
public string MorphoDerivation { get; set; }
public Morph(int morphoID, string morphoDerivation)
{
this.MorphoID = morphoID;
this.MorphoDerivation = morphoDerivation;
}
}
public class Sem
{
public int SemID { get; set; }
//public string MorphoDerivation { get; set; }
public Sem(int semID)
{
this.SemID = semID;
}
}
}
However, I found that the result is built as a new DataGrid that has not any designed form. I mean that the detail tabs that I define in the Designer are not appeared in the resulted grid.
The result is as follows:
Notes
The design of the resulted grid which is totally different from my design, I think it is just like the Lists objects.
The other problem which is the appearance of :
"WindowsFormsApplication2.Morphos" and "WindowsFormsApplication2.Semantics" at the cells of the grid rather than the values that I passed!

Firstly, you should create associations between your data object properties and GridView columns via GridColumn.FildName property.
For your main view (gridView2) it looks like this:
// gridColumn1
this.gridColumn1.Caption = "ID";
this.gridColumn1.FieldName = "x"; // associate this column with Term_Space_Grid.x property
this.gridColumn1.Name = "gridColumn1";
Please read the following article for more details: Creating Columns and Binding Them to Data Fields
Secondly, you can not directly bind columns to object's nested properties (for example to MyExpansions.semantics.subclasses.SemID).
To bypass this restriction you can use several approaches:
The simplest approach is using Unbound Columns and the corresponding ColumnView.CustomUnboundColumnData event (you can handle this event to provide data from nested objects).
You can also use the approach demonstrated in the following KB article: How to display and edit complex data properties in grid columns
Thirdly, to get official and guaranteed answer you should address any urgent question related to any DevExpress products directly to DevExpress Support Center.

Related

How inheritance variables from another class?

I don't know how to inheritance a variables from another class. I write code in C# and I created two classes
First one is Osoba (engl. Person) which has variables ime, prezime, OIB (engl. name, last name, ID) and I have another class Racun (engl. account) which means bank account.
Class Racun has variables podaci o vlasniku računa (engl. account holder information), broj računa (engl. serial number of account) and stanje računa (engl. bank account balance).
Well podaci o vlasniku računa (engl. account holder information) needs to have variables from class Osoba. How can I do that?
I will show you my two created classes with code. If you notice both classes need to have 3 variables, I didn't create first variable in class Racun (engl. account) because the first one need to contain variables from class Osoba (engl. Person).
Osoba.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Vjezba6_1
{
class Osoba
{
public string ime { get; set; }
public string prezime { get; set; }
public int oib { get; set; }
public Osoba(string tempIme, string tempPrezime, int tempOib)
{
this.ime = tempIme;
this.prezime = tempPrezime;
this.oib = tempOib;
}
}
}
Racun.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Vjezba6_1
{
class Racun
{
public int brojRacuna { get; set; }
public int stanjeRacuna { get; set; }
public Racun(int tempPovr, int tempbrojRacuna, int tempstanjeRacuna)
{
this.povr = tempPovr;
this.brojRacuna = tempbrojRacuna;
this.stanjeRacuna = tempstanjeRacuna;
}
}
}
If your povr variable needs to hold the same pieces of information as in Osoba, you can either have povr be a reference to an instance of Osoba:
class Racun
{
public Osoba povr { get; set; }
public int brojRacuna { get; set; }
public int stanjeRacuna { get; set; }
public Racun(Osoba tempPovr, int tempbrojRacuna, int tempstanjeRacuna)
{
this.povr = tempPovr;
//etc
Or you could make a struct to hold common information:
namespace Vjezba6_1
{
struct PodaciOVlasnikuRacuna //i'm sure you can shorten this, but i don't know the language
{
public string ime;
public string prezime;
//other account holder information
}
}
And use this in your classes, like so:
namespace Vjezba6_1
{
class Osoba
{
public PodaciOVlasnikuRacuna podaci { get; set; }
public Osoba(string tempIme, string tempPrezime, int tempOib)
{
this.podaci.ime = tempIme;
this.podaci.prezime = tempPrezime;
this.podaci.oib = tempOib;
}
}
}
namespace Vjezba6_1_v2
{
class Osoba
{
public Podaci povr { get; set; }
public Osoba(string tempIme, string tempPrezime, int tempOib)
{
this.povr.ime = tempIme;
this.povr.prezime = tempPrezime;
this.povr.oib = tempOib;
}
}
}

.Add does not exist in the current context

I'm creating my first app in Xamarin.forms and want to add information about the characters. I followed the Microsoft docs but I keep getting the error that ".Add does not exist in the current context"
I've been the last hour or two searching online but nothing seems to have fixed it. Any help would be greatly appreciated, thanks!
using SQLite;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace CharCreator
{
public class Character
{
[PrimaryKey, AutoIncrement]
public int charIndex { get; set; }
public string charName { get; set; }
public string charClass { get; set; }
public string charRace { get; set; }
public int[] charStats { get; set; }
public int classId { get; set; }
public string className { get; set; }
}
}
public class CharClasses
{
List<CharClasses> classList = new List<CharClasses>();
classList.Add(new CharClasses() {classId = 1, className = "Barbarian"});
}
Your problem begins with the declaration
List<CharClasses> classList = new List<CharClasses>();
You are declaring a List of CharClasses instead of a List of Character. Then you try initialize this list with a first element. But you cannot add code outside a method.
So, if you really need to have CharClasses initialized with a List<Character> containig at least one element then you need to write this
public class CharClasses
{
public List<Character> classList = new List<Character>()
{
new Character {classId = 1, className = "Barbarian"}
};
--- other class method follows
}
This syntax is explained in documentation at Object and Collection Initializers

How to add a gridview to a C# winforms project with a list of objects as the datasource

I'm building a winforms application with C# in Visual Studio 2015 community. In this project I have a class built as so:
public class EDIFile
{
public string fullInFilePath { get; set; }
public string fullOutFilePath { get; set; }
public string InfileName { get; set; }
public string OutfileName { get; set; }
public string UniqueID { get; set; }
public DateTime infileDateTime { get; set; }
public DateTime outfileDateTime { get; set; }
public TimeSpan timeDiff { get; set; }
}
I have a list built of this class. After it is loaded I would like to have a gridview that is populated with the contents of this list. I've looked online and I've found a couple of solutions but none of them have worked for me. Please help me out with some specific instructions if you can. Thanks in advance.
I still haven't gotten it to work for me yet. Based off of the two answers here is the code that I have so far:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ProviderPayProject1
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load_1(object sender, List<EDIFile> EDIFiles)
{
DataGridView dataGridView1 = new DataGridView();
dataGridView1.AutoGenerateColumns = true;
Controls.Add(dataGridView1);
dataGridView1.DataSource = EDIFiles;
}
}
}
this is the code from "form2" that is called from "form1". all "form2" should do is load and populate a datagridview based off of a list that is passed to the form. Please help me know what I'm doing wrong.
Not entirely sure I understand your question, if you are looking to create DataGridView through code you could do this.
List<EDIFile> data; // construct your data.
DataGridView grid = new DataGridView();
grid.AutoGenerateColumns = true;
this.Controls.Add(grid);
grid.DataSource = data;
Other option, add DataGidView control through designer and set the DataSource.
ex..
List<EDIFile> data; // construct your data.
dataGridView1.DataSource =data;
You could use the following code, its pretty simple. When the form is loaded it sets the DataGridViews datasource.
Steps are pretty simple:
Create winform app and just add one control, a DataGridView and name it. In this example its simply named dataGridView1. You'll need to figure this step out yourself though.
Determine how the DataSource for how the DataGridView will be set, in this example, it is set when the form is loaded, the Form1_Load() function. You could do this based on a click of a button.
Create code to create a List<EDIFile> list. In this example GetDataGridViewData() returns List<EDIFile>. It basically creates 10 dummy EDIFile objects
Set DataSource of the DataGridView
Assuming you have the winform from the first step, you should be able to change the namespace WindowsFormsApplication1 and the Form class Form1 to what you need:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
// the list of EDFiles
public List<EDIFile> EDFiles { get; set; }
public Form1()
{
InitializeComponent();
Load += Form1_Load; // add Form Load eventhandler
}
/// <summary>
/// Called when the form is loaded
/// </summary>
private void Form1_Load(object sender, EventArgs e)
{
// get dummy data
EDFiles = GetDataGridViewData();
// set datasource to the dummy data
dataGridView1.DataSource = EDFiles;
}
/// <summary>
/// Returns dummy data for the datagridview
/// </summary>
/// <returns></returns>
private List<EDIFile> GetDataGridViewData()
{
// bascially just creates dummy data for the example,
// you'll need to implement based on how you need it to be
var newEDFiles = new List<EDIFile>();
Random random = new Random();
for (int i = 1; i <= 10; i++)
{
int randomNumber = random.Next(0, 100);
var infileDateTime = DateTime.Now;
var outfileDateTime = infileDateTime.AddDays(randomNumber);
var edfile = new EDIFile()
{
fullInFilePath = "fullInFilePath" + i,
fullOutFilePath = "fullOutFilePath" + i,
InfileName = "InfileName" + i,
OutfileName = "InfileName" + i,
UniqueID = "UniqueID" + i,
infileDateTime = infileDateTime,
outfileDateTime = outfileDateTime,
timeDiff = outfileDateTime- infileDateTime
};
newEDFiles.Add(edfile);
}
return newEDFiles;
}
}
public class EDIFile
{
public string fullInFilePath { get; set; }
public string fullOutFilePath { get; set; }
public string InfileName { get; set; }
public string OutfileName { get; set; }
public string UniqueID { get; set; }
public DateTime infileDateTime { get; set; }
public DateTime outfileDateTime { get; set; }
public TimeSpan timeDiff { get; set; }
}
}
My example looks like this:
In the Form1 class for the button click event you'll need the following:
var f2 = new Form2();
f2.ShowForm(GetDataGridViewData());
And Form2 class should look like this:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public void ShowForm(List<EDIFile> EDIFiles)
{
DataGridView dataGridView1 = new DataGridView();
dataGridView1.AutoGenerateColumns = true;
Controls.Add(dataGridView1);
dataGridView1.DataSource = EDIFiles;
this.ShowDialog();
}
}

How can I query different tables dynamically with LINQ?

So I'm not sure if you can do this or not, but I would like to avoid using SQL strings if I can. What I would like to do with Linq/DbContexts is the following that can be done easily with SQL:
string sql = "UPDATE " + tableName + " SET Status=0 WHERE Id=" + formId.ToString();
I can easily put this into a loop where tableName and formId are given dynamically and execute no problem.
I have multiple DbContexts, so I don't know of any way to do something like:
var db = new *dynamicallyChosenContext*()
var query = from p in db.*dynamicallyChosenAlso*
where p.Id == formId
select p;
foreach (var result in query)
{
result.Status = 0;
}
db.SaveChanges()
Thanks for the help!
Here is a piece of working code that can update different tables at runtime from different contexts without using reflection.
namespace DemoContexts
{
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
public interface IThing
{
int Id { get; set; }
int Status { get; set; }
}
public class FirstPersonThing : IThing
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int Status { get; set; }
public string Foo { get; set; }
}
public class SecondPersonThing : IThing
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int Status { get; set; }
public string Bar { get; set; }
}
public class FirstContext : DbContext
{
public FirstContext() : base("FirstContext") { }
public DbSet<FirstPersonThing> MyThings { get; set; }
public DbSet<SecondPersonThing> YourThings { get; set; }
}
public class SecondContext : DbContext
{
public SecondContext() : base("SecondContext") { }
public DbSet<FirstPersonThing> MyThings { get; set; }
public DbSet<SecondPersonThing> YourThings { get; set; }
}
class Program
{
static void Main(string[] args)
{
int contextType = 1;
int thingType = 1;
DbContext db = RunTimeCreatedContext(contextType);
IQueryable<IThing> collection = RunTimeCreatedCollection(db, thingType);
UpdateRuntimeDeterminedThings(db, collection, 1);
Console.ReadLine();
}
public static void UpdateRuntimeDeterminedThings(DbContext db,
IQueryable<IThing> collection,
int formId)
{
var querySet = collection.Where(p => p.Id == formId).ToList();
foreach (var result in querySet)
{
result.Status = 0;
}
db.SaveChanges();
}
static DbContext RunTimeCreatedContext(int contextType)
{
if (contextType == 0)
{
return new FirstContext();
}
else
{
return new SecondContext();
}
}
static IQueryable<IThing> RunTimeCreatedCollection(DbContext db, int thingType)
{
if (thingType == 0)
{
return db.Set(typeof(FirstPersonThing)) as IQueryable<IThing>;
}
else
{
return db.Set<SecondPersonThing>();
}
}
}
}
The first thing to note is that all this is statically typed so to perform a generic query against different types of objects these objects must have common property signatures and this conceptually is expressed in the IThing interface.
A second thing to note is how the IQueryable is generated. It is generated by the DbContext.Set Method (Type) in the first instance (for the FirstPersonThings), it is generated by the DbContext.Set<TEntity> Method in the second instance. The first uses a type determined at runtime and requires a cast (but could be useful to use passing types at runtime), the second uses generics and the types are determined at compile time. There are obviously a number of other ways that this function could work.
Finally the method UpdateRuntimeDeterminedThings works because it uses properties and methods that are shared across the types (either with base types/inheritance or by the implementation of interfaces).
None of this is actually dynamic programming (which is possible using the dynamic type) and I have used the term runtime determined rather than dynamic to describe how this works.
There is a technique in functional programming, called Currying, where you could pass as much parameters as you want, so you are able to access them.
Here is an exemple: http://blogs.msdn.com/b/sriram/archive/2005/08/07/448722.aspx
P.S: You could use a currying function to iterate through yours DBContexts.
I think you have to use reflection if you want to use 'code' and not sql strings. That's just how C# works... This is how you could do it:
using System;
using System.Data.Entity;
using System.Linq;
public class TestContext : DbContext
{
public DbSet<Box> Boxes { get; set; }
public DbSet<Thing> Things { get; set; }
}
public abstract class Base
{
public int Id { get; set; }
}
public class Box : Base
{
public string Title { get; set; }
}
public class Thing : Base
{
public string Name { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
var db = new TestContext();
DoIt(GetPropValue(db, "Boxes") as IQueryable<Base>);
DoIt(GetPropValue(db, "Things") as IQueryable<Base>);
}
private static void DoIt(IQueryable<Base> b)
{
Console.WriteLine(
b.Single(t => t.Id == 1).Id);
}
private static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
}
Obviously you can then put the strings in a list etc, whatever you need.

Add temporary property to list of objects

I have 3 models
public class Payroll
{
public int ID { get; set; }
public DateTime Date { get; set; }
public int PayCategoryID { get; set; }
public virtual PayCategory PayCategory { get; set; }
}
this one:
public class PayCategory
{
public int ID { get; set; }
public string PayScenario { get; set; }
public int PayGroupID { get; set; }
public virtual PayGroup PayGroup { get; set; }
}
and this one:
public class PayGroup
{
public int ID { get; set; }
public string Label { get; set; }
public string Description { get; set; }
public string EntryType { get; set; }
}
If I create a List of Payroll I will only get a list of Payroll objects with 4 properties each.
I want a list of , where each Payroll object will have the fields
Date, PayScenario, Label, Description, and EntryType. I know these can be easily obtained by
Payroll.PayCategory.PayScenario
Payroll.PayCategory.PayGroup.Label
etc.
But I am exporting these to an excel document using this generic method:
public static void Export(List<T> data, string name, Controller controller)
{
XLWorkbook workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add(name);
worksheet.Cell(1, 1).InsertTable(data);
controller.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheet.sheet";
controller.Response.AddHeader("content-disposition", String.Format(#"attachment;filename={0}.xlsx", name.Replace(" ", "_")));
using (MemoryStream memoryStream = new MemoryStream())
{
workbook.SaveAs(memoryStream);
memoryStream.WriteTo(controller.Response.OutputStream);
memoryStream.Close();
}
controller.Response.End();
}
I call from controller like this:
public ActionResult ExportData()
{
var payrolls = (List<Payroll>)Session["payrolls"];
ExportToExel<Payroll>.Export(payrolls, "Payroll", this);
return RedirectToAction("Index");
}
And the results of course give me a simple table with only the value Date in it, (plus some other trash columns like System [...] PayCategory)
Ultimately, I want the properties of these 3 models to be merged (excluding ID's) to give me a single list that I can pass on to the ExportData method. As in, is there a way to add a column to a list of objects? Something similar to
for(int i = 1; i<payrolls.Count; i++)
payrolls[i].Add.(payrolls[i].PayCategory.PayScenario);
which of course, doesn't work.
Please don't ask why I don't simply have one model instead of these 3. It's not an option unless I want to hard code values.
Thanks
If you can import Linq, you can do something like:
var payrolls = from aPayroll in (List<Payroll>)Session["payrolls"]
select new {
Date = aPayroll.Date,
PayScenario = aPayroll.PayCategory.PayScenario,
Label = aPayroll.PayGroup.Label,
Description = aPayroll.PayGroup.Description,
EntryType = aPayroll.PayGroup.EntryType
};
That would create an anonymous type with the five properties you want.
Assuming you're using ClosedXML, you should also be able to create a DataTable and send it directly to a worksheet.
What you are looking for is an "Anonymous Object".
Example usage:
var anonymousObject = new
{
ID = payrollObj.Id,
// other payroll properties
PayScenario = payrollObj.PayCategory.PayScenario
// other extended properties
};
Here's an article about them
http://www.c-sharpcorner.com/UploadFile/ff2f08/anonymous-types-in-C-Sharp/
The suggestion here is to create a new anonymous object within your loop and pass that onto your excel function instead of the original payrollObject.

Categories

Resources