WPF Datagrid UserControl with definable columns - c#

I have an object something like this:
public class Item
{
public string Name;
public int Id;
public int Quantity;
public decimal Volume;
public decimal Cost;
}
I'm wanting to create a reusable user control which would take a list of these objects and display them in a datagrid. The trick is that I want to specify which of the properties are shown in the datagrid for each instance of the control. Unfortunately my WPF skills are not up to the tasks and I don't want to create a specific control for each combination that I will want to use, as that feels like a lot of work for very similar code items. Any help to pointers of how to accomplish this would be greatly appreciated.

You can use the Columns property of your datagrid to interact with the columns and hide the columns you don't want.
datagrid.Columns.RemoveAt(IndexOftheColumn);
or if you named your columns
datagrid.Columns.RemoveAll(x => x.Name = "column name");
or if it is possible that you will need to column later
datagrid.Columns[IndexOftheColumn].Visibility = Visibility.Collapsed;
It is also possible to do this with pure Xaml with bindings but since you are new to Wpf I would suggest doing it in the code behind (the .cs of your Wpf control) first.
As for selecting which columns to hide you can pass a list of names for the columns you want to remove in the constructor of the control or with a binding. There are a lot of ways to do it.
Or you could do the opposite and add columns dynamically based on your needs.
Note that this question has been asked before

Related

Use DataBinding to maintain the alphabetic short between listBoxes

I've been programming some little project in Visual Studio using c# (.NET FRAMEWORK) and in some of my windows forms I want to show in different lisboxes the information about some object.
In my program I got a class named Client that has some Properties: an int called DNI (this is the one that identifies a Client), a string called Name and an int called Telephone. I want a form to show 3 different listboxes, each one with the list of elements of a collection of Client objects. The point is that a Client object has it's Properties showed in the same index of each listBox (to be said, reading horizontally you see the three values of the properties). I have implemented a button in top of each one that alphabetically sorts the elements of the listBox, but I would like to make a Binding between them so When you alphabetically sort one listbox, the other two sort their elements to match the new order of elements in the one alphabetically sorted.
I've been told the class DataBindingscan be used to do this. I've tried searching on the internet about it but achieved nothing and reading the documentation didn't help either, so I ended up posting it here. How can I use DataBindings to solve this? Any help or hint will be appreciated, thanks in advance.
What must I write to bind the indexes of them?
I recommended a datagridview; you seem to have tabular data that you want to show in a tabular fashion.. However, we'll demo all of it.
Easiest route:
Make a new winforms project
Add a DataSet type of file, open it, right click the design surface and choose Add .. DataTable
Name the table Client
Right click it and add column, call it DNI, use the props grid to make its type Int32
Add a string column Name
Add an int column Telephone
Save, switch to Form1 designer
Open Data Sources window (View menu, Other Windows)
Drag the Client node onto the form. A datagridview appears along with some stuff in the tray. Remove the navigator; it's not so useful in this context
Add 3 listboxes to the form
For each listbox:
Use the props grid to set its DataSource to the bindingsource
Set the DisplayMember to a different column - one DNI, the other Name and the third Telephone
That's it for now, run the app. Type some data in the datagridview. Note that when you sort by clicking the DGV header, the listboxes follow; this is because the sort instruction is being carried out by the bindingsource, and all controls bind through the bindingsource:
So that's thngs bound through a bindingsource to a strongly typed datatable, which is conceptually not really any different to what you have. The bit of work making the table and its columns in the design surface is the notional equivalent of making a class with properties. Indeed if you were to open the DataSetBlahBlah.Designer.cs file you'd find a class ClientRow with 3 properties DNI, Name, Telephone
You could change up everything you've made to be based on e.g. a List<Client> but your sorting life becomes slightly more awkward because a BindingSource doesn't understand how to sort it. As such you'd end up with something like:
//class property
private List<Client> Clients = new();
//in constructor
clientBindingSource.DataSource = Clients;
//in button that does sorting:
clientBindingSource.DataSource = Clients.OrderBy(c => c.name); //etc
Personally I'd leave it as a strongly typed datatable; for what you'd want out of a List<Client> a ClientDataTable collection of ClientRow are surface similar enough..
Clients.Where(c => c.Name == "John"); //how you might search a List<client>
ClientsDT.Where(c => c.Name == "John"); //how you might search a ClientDataTable
Clients.Add(new Client(){ DNI = 1, Name = "a", Telephone = 1 } ); //add to a List<Client>
ClientsDT.AddClientsRow(1, "a", 1); //how you might add to a ClientDataTable
etc
If you have already implemented a button for each, you've almost finished.
Every ListBox have to be bound with a List of Client, showing a specific property as DisplayMember.
The button of each ListBox can sort the List and refresh all of the ListBoxes.
If you want more information, please post some of your code.

Autocomplete TextBox for C# Winform VS2008 clarification needed

I am working on C# winform vs2008 project. Requirement is to show line level details into grid and grid one text box cloumn user will type the text and it should populate the autocomplete text. Autocomplete search should based on one column only, but need to show additional one column to user. Exampe : Name and Phone number. user will search based on Name only additional column phone should display purpose.
I have following query :
1) Database is large, is there any free autocomplete 3 party tool available.?
2) How can i show muliple columns in autocomplete.
Please let me know, how i can show multiple columns in autocomplete.
I am stuck here.. please help me out..
Thanks and Regards
Ram
There are third party components that can be used to support multiple column drop down, for example DevExpress's LookUpEdit, Infragistics's UltraCombo and Telerik's RadMultiColumnComboBox. You can change the filter then popup the dropdown when typing, but that is not going to beat the performance of Windows's autocomplete, which uses a second thread to enumerate candidates.
If you have that much data, auto-sizing the drop down columns and animation probably need to be disabled if your control library enables them by default.
public Class YourClass
{
public string Name;
{
get;
private set;
}
public string PhoneNo;
{
get;
private set;
}
public override string ToString()
{
return String.Format("{0,-50} {1,-15}", this.Name, this.PhoneNumber);
}
}
internal class YourForm : Form
{
ComboBox YourComboBox = new Combobox();
//Set the style of your combobox such that it looks like a text box
BindingList<KeyValuePair<string, YourClass> bl = new Binding<string, YourClass>();
//Query for the data to populate the BindingList
//Lets say you put the UserId or ContactId of the person in the Key..
YourComboBox.DataSource = bl;
YourComboBox.DisplayMember = "Value";
YourComboBox.ValueMember = "Key";
}
Do what ever you are doing for autocomplete
There's no ready and elegant implementation for what you need. What I gave you would display the results like in a table..
Eg:-
Reese W 32
Pamela A 40
but with the name, taking about characters of space in what ever font the control renders..
(You will have to look at this answer in edit mode to see it)
If you want exactly what you need, you WILL have to use some available 3rd party controls or write one of your own. And as some one said, it's too much of code..

How to refer to an object name through a variable?

I have some code that will open a sqllite database, get some street names, and populate a list box that is then attached to a combo-box so it can suggest the names as the user types them. I want to make a procedure that I can call to do this since it will be used on may different combo-boxes. I can pass it the name of the control, but how do I modify attributes of a contol while referring to it as a variable?
Something like:
string A = "cbSTreets"
[A].text = "Sets the Text for the combo box."
If someone could just point me in the right direction I would appreciate it.
Instead of passing it as the name of a control, why not just pass the control itself (especially if they're all comboboxes and the same type?)
Alternatively if for some reason you can't pass the control itself, you could set something up with a datastructure like a dictionary if you need to use the string name:
Dictionary<string, ComboBox> comboBoxes = new Dictionary<string, ComboBox>();
//Use the string you want to refer to the combobox and the combobox item itself
comboBoxes.Add("bcbsTreets", comboBox1);
//Use the name as defined in the previous step to get the reference to the combobox and
//set the text
comboBoxes["bcbsTreets"].Text = "whatever";
You could try something like this:
private void SetText(List<string> streets, ComboBox cb)
{
cb.DataSource = streets;
}
Of course, you'll need to fill the streets from your database and pass in the ComboBox control you want to populate. You can use another collection if you like, but ComboBox datasources need to implement the IList interface.
This is only possible via reflection and should be avoided!
You should do this the normal way.
For the solution how to do it with reflection, look here: How to access class member by string in C#?

Pass in class object to usercontrol

Hi how do i pass in a class object from UI Form to the user control datagridview?
I created a user control which it has a datagridview, a search textbox on top of datagridview, and a label to show total count. and i would like to have the following feature to be written in that control.
Show Total count for that object bounded to datagridview.
TextChange event to filter the data in datagridview.
I would like the above features to be written in Usercontrol as i felt it is redundant to repeat that in UI Form.
For this, I created a datasource in the usercontrol
public object Datasource { get; set; }
1) If my class object is e.g. User, how do i get the type of the datasource converted to User and get the Count of total User and bind to the label in the usercontrol?
2) I felt it redundant to write this below in every form. How do i simplify this and make this run in the userControl itself by using the datasource i pass in to it.
private void BaseCRUDForm_GridViewTextChangedSearch(object sender, EventArgs e)
{
if (sender.ToString().Length > 0)
{
Users = Users.Where(x => x.Name.StartsWith(sender.ToString())).ToList();
}
else
{
Users = Repository.UserRespository(false).GetAllUsers();
}
UserBindingSource.DataSource = Users;
}
Please advice.
While creating the object of user control, There are two ways to forward the data in user control
Initialize the property. The Property will have the object type which can be cased later while binding to grid.
pass the data to constructor.
I feel that you should have constructor i.e point 2.
Now after casting this object, you can populate the label as well as the grid.
I hope this will help you.

Databinding to a custom control

I have following situation in a C# Windows Forms (.NET 4.0) application:
I have a bindingsource which datasource is set to a collection of objects of a custom class.
Most properties of this class can be represented by a textbox or checkbox, as they are strings or numbers or bools.
However, there is one property, called Ratings, which is another custom object and must be represented by a custom control I developed.
I have bound a datagridview to the bindingsource, and obviously the dgview displays the numbers, strings and bools correctly. But on the same form I also have an instance of the custom control I developed, and so want I want to do now is bind my custom control to the same bindingsource as the datagridview uses, and to the specific datamember called Ratings. But I don't have the slightest clue on how to start. I suspect I must implement some interface which implements DataSource and DataMember on my control, but not sure where to begin. So basically what I want is each time the selected item is changed by means of selecting another row in the datagridview, the according Ratings property is represented in the custom control.
Right now the endresult that I wish to achieve is working, but I do this by refreshing my custom control each time the OnSelectedRowChanged event of the datagridview is firing, and associating the Ratings property of the selected item to the custom control.
But I was wondering if I could achieve this purely by the databinding mechanism in .NET.
Thanks for any replies !
Mathieu
ps: to further clarify, as it doesn't seem so clear in pure text:
Psuedo-code representing the object that I use as datasource for the bindingsource is:
public class Car
{
private string number;
private string name;
...
private Ratings ratings;
public string Number
{
get { return this.number; }
set { this.number = value; }
}
public string Name
{
get { return this.name; }
set { this.name = value; }
}
...
public Ratings Ratings
{
get { return this.ratings; }
set { this.ratings = value; }
}
}
So I want all the string and number properties from the bindingsource to bind to the datagridview, but I need the Ratings property to bind to the custom control.
I understood that you'd like to have a special column in the DataGridView with your custom control. To do this, you need to create a subclass of DataGridViewCell and DataGridViewColumn and implement IDataGridViewEditingControl.
See MSDN for an example.
You can read this Microsoft article about interfaces related to data binding. The ones of your interest are at the bottom under "Interfaces for Implementation by Component Authors" section.

Categories

Resources