how to bind data to gridcontrol in WPF - c#

I am trying to use LINQ to select data from database and bind it to DevExpress GridControl. I have succeeded yet though. here is my code below. It doesnt bind anything, how can I fix this???
public ucEmailList()
{
InitializeComponent();
ARYADA_EMAIL_DBEntities db_ = new ARYADA_EMAIL_DBEntities();
var elements = from element in db_.TEST_EMAILS
where element.ID >4
select element;
gc.DataContext = elements;
}

Use ItemsSource
gc.ItemsSource = elements.ToList();
Anyway this is poor idea. Why don't you use ViewModel that provides data from a database and bind it in a XAML to proper property of GridControl?
EDIT - the way I would do it
Remove the code from code behind that initializes gc
Provided you have somewhere in your XAML a GridControl you should also have its property bound:
<dexp:GridControl //.... some properties
ItemsSource={Binding Data} />
Inside view initialization (see point 1) set DataContext to you view model that contains property Data which actually gets data from a repository.
Make sure data are not directly objects from the database. Remap them to your Domain objects. To save some time you can use AutoMapper.

For your scenario, you can just change one line:
gc.ItemsSource = elements.ToList()
ToList() is required because elements has yet to be calculated and the control does not like binding to it.
For reference, elements was defined as:
var elements = from element in db_.TEST_EMAILS
where element.ID >4
select element;
Do you want to know more?
Later, if you are interested in the mvvm pattern for wpf I recommend this article:
Implementing the MVVM Pattern Using the Prism Library 5.0 for WPF

Related

Using ViewModels in ObservableCollections in Prism

As far as I know, the default way to use a ObservableCollection that is bound to a listview is with model classes as elements (ObservableCollection<MyModel>). So when a listview element is selected, we use NavigateAsync and pass the model, which then can be used by the ViewModel to "fill itself".
The problem with this approach is, that it's not possible to use ViewModel properties for binding in the listview.
For example:
I have a View, ViewModel and Model "PickList", which contains a collection of "PickLine" objects - each having a View, ViewModel and Model themselves. The PickLine object contains a property "PickedQuantity" and a property "OpenQuantity". Now in my PickList view, I don't want to bind these two to separate items (e.g. two labels), but I want to have one label to display both I a format like for example "PickedQuantity / OpenQuantity". I know this example can be solved by using multi binding or something like this. But that's not the meaning of it all.
My PickLine ViewModel already has a property "QuantityString", that I want to bind to the label of a listview element via DataTemplate. But how can I do this. Is it even possible?
Make a property that combines the two other properties and bind to that. E.g.:
public string FullQuantity {get {return $"{PickedQuantity} / {OpenQuantity}";}}
Then in the setter for PickedQuantity and OpenQuantity, you will want to call whatever PropertyChanged method you have set up to notify the bindings of a property change and pass in the FullQuantity property name so elements that are bound to FullQuantity get updated when either PickedQuantity or OpenQuantity are changed.
This way, you are only binding one label's text to one property and that label would get updated when either of the two quantity properties are changed.
Note: I am unfamiliar with Prism, but this approach should work regardless of the Mvvm framework in use.
Your PickListViewModel should expose a collection property whose items are of type PickLineViewModel (not PickLine).
Whether you need an ObservableCollection<PickLineViewModel> depends on where changes can happen - in service / model that initially created the PickLines or in the GUI or both. In any way, you have to make sure the changes are propagated from one side (the collection of view models) to the other (the collection of models). Google wrapping observable collection as a starter (hint: avoid two-way sync if possible). These blog posts are old but still relevant and make a good reading. A trivial wrapping is described in this answer.

Why should I avoid instantiating a CollectionView directly?

The documentation of the CollectionView class says:
You should not create objects of this class in your code. To create a collection view for a collection that only implements IEnumerable, create a CollectionViewSource object, add your collection to the Source property, and get the collection view from the View property.
In other words, I am supposed to write:
var cvs = new CollectionViewSource();
cvs.Source = myData.Where(d => someCondition(d));
var view = cvs.View;
instead of
var view = new CollectionView(myData.Where(d => someCondition(d));
However, the documention fails to explain why I should do that. Both options seem to work.
What bad things will happen if I choose option 2 over option 1?
There are a few specializations of the CollectionView class, like for example ListCollectionView. Whenever you bind to some collection, there is a view automatically generated for you based on the type of the source collection. Instead of explicitly creating a CollectionView or a CollectionViewSource, you can get the default view of a collection by using the static CollectionViewSource.GetDefaultView method:
ICollectionView view = CollectionViewSource.GetDefaultView(myData);
It will return a ListCollectionView if myData implements IList.
It's perfectly fine to expose an ICollectionView from a view model if you perform the filtering or sorting in there. A CollectionViewSource is mainly used when you want to perform the filtering, sorting or grouping of a source collection in the view.
Binding CollectionView may present problems down the road if you want to change the way your data is displayed.
From the CollectionViewSource documentation:
Because a view does not change the underlying source collection, a source collection can have multiple views associated with it. By using views, you can display the same data in different ways. For example, you can use two views on a collection of Task objects to show tasks sorted by priority on one part of the page and grouped by area on another part of the page.
Binding directly to a single CollectionView limits the ways you can display your data.In short, CollectionViewSource plays nicer with your collections in XAML when binding.

How can i modify XAML elements from another class (C#-WPF)

I am trying to connect a class called Engine with XAML elements, to be more specific I have a LevelWindow.xaml where a grid exists. I want to split that grid (in rows and columns ) from Engine class, the split code exists, but when the programs is running Engine is not changing grid from LevelWindow .... I tryed to semi-use bindings, but i cant find any way to Bind the GRID .... some sugestions ?
Engine
If you absolutely want to use your existing splitting code and that it doesn't support binding and/or notify property changed, you can perhaps find some way to perform what you want using a ContentControl instead of your Grid in your xaml file.
Then Bind the contentControl content property to a grid that you instantiate in your Engine (thus you can access and modify it's inner properties like grid column/rows).
Yet it's quite horrible to perform graphic control instantiation in your business class...
Link to MSDN contentcontrol :
https://msdn.microsoft.com/fr-fr/library/system.windows.controls.contentcontrol(v=vs.110).aspx

Correct way to use a DataGrid when utilizing a LINQ2SQL DataContext table as its ItemsSource (best practices)

So, I am learning Linq2SQL by building a simple UI. I am using two DataGrids to display a master/details type interface, where "Customers" are displayed in one grid and, when selected, some details displayed in the other grid (for example, records from a foreign key table such as "Orders", whatever).
Now, every example I have read regarding the use of a DataGrid shows something like this:
using( var db = new TestDataContext() )
{
// AutoGenerateColumns set to false and
// column bindings set to certain properties
// of the Customer class.
grid.ItemsSource = db.Customers.ToList();
}
Well, that doesn't work because the DataContext is accessed after this code is executed due to data binding, and of course, the Context object has already been disposed. Ok, that's fine; I can use a single DataContext for all of my grid operations, even though the DataContext class was designed to be used and disposed of quickly. I'm not sure if keeping a single DataContext around is going to bite me in the future yet.
So now I run into the issue of updating the database and reflecting those changes back to the grid(s). The simplest way I have come across is to set ItemsSource to null and then bind it once again to the table. This just feels 'dirty' to me and I have to imagine I am missing something. In theory I could use an ObservableCollection and bind that to the grid, keeping it in sync with the underlying data, but I haven't yet figured out how to get the grid to display data from the observable collection (I bind it in XAML and only empty rows are rendered in the table).
TLDR:
So anyway, my question is this; what patterns do you experienced LINQ2SQL guys use for this type of a scenario? It seems that all of the examples I can find are overly simplistic and don't quite apply in a real world use case (even one as simple as mine). Basically, how do you use your DataContext, how do you keep the grid updated when new items are added to a table, and what are some general best practices here?
In the example code you provided, the datacontext would only be getting accessed again by bindings if you are binding to lazily loaded properties.
Have you looked at the LoadOptions.LoadWith<>() function on the datacontext (assuming it hasn't been renamed since I last looked at linqtosql)
Personally I have no problem taking a hold of the datacontext and keeping it around for the page life, though not a single one for the whole application life.

Binding two Observable Collections with each other

I have two properties of ObservableCollection<string> type (in separate projects); What I want to do is to bind these two using reflection and SetBinding like this -
//Get the PropertyDescriptor for first collection property
PropertyDescriptor relatedPropertyDesc = prop.Find(firstCollPropName, false);
Binding relatedPropBinding = new Binding(relatedPropertyDesc.Name);
relatedPropBinding.Source = this.SelectedItem;
relatedPropBinding.Mode = BindingMode.TwoWay;
//Bind the second collection property using binding created above
propItem.SetBinding(MyItem.SecondCollProperty, relatedPropBinding);
This SecondCollProperty is then bound to a ComboBox's ItemsSource.
As such this works correctly, values present in firstCollProperty are displayed correctly in combobox; but if some changes are made in firstCollProperty at run time then they are not reflected in ComboBox!(adding new items or creating new collection object).
Changes are reflected correctly after refreshing the binding(again executing the above code).
My question is - If two ObservableCollections are binded together why any changes in first doesn't get reflected in other? but same thing works for properties of string or double type.
Is there any way of achieving this?
Just going through some old unanswered questions and saw this. Undoubtedly you've come up with a workaround by now, but my recommendation would be look into something like CLinq, Bindable Linq, or Obtics for this. See this question for more details. You'd take the first collection, create a dynamic query against it, and expose that dynamic query (which implements IObservableCollection) as your second property.

Categories