Winforms .net 2.0: binding a textbox to a parent property - winforms

I've got a strongly typed dset, w/two datatables: Parent and Child, w/a relation linking them in the way you'd expect (e.g. parent-has-many-children).
On my Child Detail form, I show lots of info on the current child, w/binding calls like so:
me.txtBirthDate.DataBindings.add(New Windows.Forms.Binding("Text", MyDataset, "Child.Birthdate"))
But I would also like to show some info on the child's parent--say, the parent's name. I have tried:
me.txtParentName.DataBindings.add(New Windows.Forms.Binding("Text", MyDataset, "Child.Parent.Name"))
and
me.txtParentName.DataBindings.add(New Windows.Forms.Binding("Text", MyDataset, "Parent.Name"))
But these both result in a blank text box.
I can of course put the parent properties directly on the Child DataTable & fill them w/the results of a join between the underlying db tables, but I'd like to avoid that if it's possible (my real app involves just a few Parents each w/many many Children & I'd like not to be moving so much unnecessary data).
Is that possible?
Many thanks!
-Roy

I usually use a BindingSource between the DataSet and the controls. When using this approach, if I have controls that I want to bind to a related row from a different table, I create a new BindingSource, which points at the related row (his DataSource property is the original BindingSource, his DataMember is the parent table), and then bind the other controls to the 2nd BindingSource.
I usually do it all in the designer view, which just creates those BindingSource objects as I go along.
Hope that helps.

Related

WPF Caliburn.Micro DataGrid columns

I have a WPF Caliburn.Micro application that has a tab control with a DataGrid in it. The columns in the DataGrid are set programmatically. I may need to close a tab, and then open it again. And I get an exception, saying a column already exists in the DataGrid, though in fact there are no columns at all. Could you please help me with this?
On the picture, you can see in the Watch window that myGrid.Columns.Count equals 0
It looks like you might be adding a column which already exists (in the previous datagrid) to another datagrid. The error says that the column exists in the Columns collection of a datagrid, not neccessarily the one you are trying to add it to
DataGrid cannot share columns - you need to remove the column from the previous datagrid. This may mean you have a memory leak somewhere too. If your tab item VM inherits Screen you might want to override OnDeactivate and clear down the columns
Alternatively, you may be able to get a reference to the parent grid via the column and remove it from it's parent, though I've not used the standard .NET DataGrid myself (just used Teleriks one) so I can't be sure - personally though, the clear down on close seems like a cleaner implementation.
It shouldn't be the responsibility of a new instance of a class to clear up after a dead instance, it should be the responsibility of the class to clean up after itself (I keep telling my kids this!)

How to assign context and refresh it in Entity Framework?

I created a new entity object and bound it to controls in another window (edit window). After modifying and saving I assigned a new entity object into the one in the main window. The old entity object is bound into a datagrid, now I want the datagrid to display the data that I had modified and saved.
ObjectContext.Refresh Method (RefreshMode, Object) seems to be what I want but I don't know how to use it correctly.
In short :
I have a main window with datagrid displaying the whole data of the table. Users can pick one row and edit it in a edit window. After saving, the datagrid should display what has been modified.
Your best bet here is to use an ObservableCollection as your data source for the datagrid instead of the query.
And look at implementing INotifyPropertyChanged interface in your Customer class.
The ObservableCollection is initially populated by the database query. User changes are made to elements within the ObservableCollection and once complete you then just need to trigger transferring the changes to wherever you originally obtained your list of Customer objects
By doing this changes made both to the collection of Customers and to individual Customer objects (if present within the datagrid) will be automatically updated for you.
edit
I must admit that I'm a bit rushed to offer up any code at the moment, but here's a pretty good article that explains how to use ObservableCollections and classes that implement INotifyPropertyChanged. It also has code examples, which although in VB.NET should give you enough of an idea to get started.
In effect you separate your code into distinct layers UI (View), business logic (View Model) and data layer (Model where your entity framework resides).
You bnd your datagrid to the ObservableCollection type property in your Customers class and your edit csutomer window is bound to as instance of your Customer class.

Building a data entry form in wpf

I'm trying to build a data entry form in wpf. To perform validation I apparently need to have an object attached in the datacontext of my grid. But how can I have one when I didn't create one yet?
How does it work?
For example, I have a screen with a datagrid. The datagrid contains users that were obtained from membership. Above the grid is a button: add user. When clicked a new window appears and the following can be entered: user name, password, email. To perform validation on the textboxes to see if they aren't empty. Now, it is my understanding that the way this works is by having an object attached to the window (datagrid datacontext). But how can I have it attached when it doesn't exist yet?
This is a case where MVVM design patterns are very useful.
Every WPF view has a corresponding view model object that the properties in the view are bound to. So your window with the data grid has a view model - its DataContext - and the view model has properties that are bound to properties in the view - e.g. the ItemsSource in the data grid is bound to a collection (see note 1).
The "add user" command (which is implemented as a RelayCommand in the window's view model) creates a new view (the new window) and its corresponding view model object (the new user), sets the view's DataContext to the view model, and calls ShowDialog to show the window. (See note 2.) If the user accepts the new object, ShowDialog returns true, and the logic in the command takes the view model object (which now contains whatever changes the user made) and uses the information in it to create a new model object and add it to the model. If the user cancels, ShowDialog returns false, and the command discards the view model object without creating a new model object.
Note 1: The collection here may be a collection of model objects, or it may be a collection of view model objects. It depends on whether or not you need anything that's not in the model for displaying the model objects in a data grid. It's common, in this kind of scenario, for the objects in the grid to be view models for the dialog - that is, the view model objects have properties implemented for both display in the grid and modification in the dialog window. On the other hand, if all the grid is doing is displaying data from the model, there may be no need for an intermediary object.
Note 2: Having the command create a WPF window violates a central MVVM design principle, which is that view models shouldn't create WPF objects. The reason for this principle is pretty simple: you can't build an automated unit test for this command, since it's just going to throw up a dialog and wait. There are all kinds of different approaches to this - see, for instance, this question, and Josh Smith's blog post on the Mediator pattern - and all of them involve delegating the creation and display of the actual dialog window to a separate service that can be mocked out for unit testing. If you don't want to choose one of those approaches up front, you can retrofit one into your application once you get this thing working.
The idea here is that you should attach an object which is slightly different from your business models. In your case it won't UserInfo (or whatever you have for users in grid). It will be some other class, more suitable for editing. In MVVM this class will be a ViewModel. This class will have some differences comparing to your regular user class, for example it may have some properties nullable (when you haven't set them yet). Also this class will handle validation. You should instantiate this class at the same time you're creating an editor window and put instance of this class into Window.DataContext.
Hmm, there is a lot in this question but I just created a screen with three data grids (I am using Telerik in this case) and under each datagrid is a button to add to the grid. No the window with the three datagrids has it's own view model. and each of the "pop up's" has it's own viewmodel, in this case all of these are user controls and I just create a new window and set window.content and call show dialog.
Communication is facilitated via "events" - not the standard events you are used to in .NET but in this case I am using Prism and it's CompositePresentationEvent class. When the user is done creating their new object they click add and I fire off this event with the "payload" being the object they created. The main window with the three grids listens for that event and has a method to handle it, in this case adds it to the ObservableCollection which is what I bind the grids to.
If I were you I would look into the various frameworks that are out there, Prism, MVVM light etc... Again, your question seemed rather broad, I tried to give an overview but I didn't go into detail, if you look into some sort of framework I think it will clear up a lot of these details for you.
When the users hit Add New, create a new blank copy of your object, and set the datacontext to that new object.
Set some kind of flag to identify that it is a New object. This can be the Id being NULL, 0, -1, etc or an ObjectState property set to New. That way all your validation rules apply, and once the user hits save you know to INSERT instead of UPDATE

How can I execute WPF filters on a background thread?

I'm using filters in WPF and I'm following the pattern suggested here.
To summarize, this involves a text property being exposed on the ViewModel which represents the text to filter by. When the property is set (by the binding from the textbox in the View) it uses CollectionViewSource.GetDefaultView(MyItems).Filter = blah to filter the visible list of items.
This works great, but the problem comes when the collection of items is very large, as the filtering is performed on the foreground thread and thus hangs the UI. Does there exist a pattern for performing filtering on a background thread, and how does this fit in the Model-View-ViewModel pattern?
Instead of using CollectionView for filtering, do your own: In your ViewModel create a property that contains the filtered data and one to hold the filter. Whenever the filter is changed, fire off a work item in a separate thread to computed the new filtered data property then update that property when it is done. When updating the property, either update the existing collection or replace it depending on how many changes were made.
I use a class I use that automates this so it is as easy as declaring the one collection to be a filtered version of the other.

WPF: How to use views like ICollectionView and IEditableCollectionView

I understand the syntax but not how really to use it. It's clear in many basic scenarios but as soon as it get's a little bit advanced I start getting a headache.
For example there are many different views but often not clear wich one to use. Also should you use always just one or mix and match. Do you use the view as your itemssource for ItemsControls?
I'm gonna give a scenario. I have items from a database that I need to show info about in a app and also allow to edit and add new. The items form a hierarchy and the models are of different types. So the top level have children and they then have children.
I could show it in a TreeView or some itemscontrol. Problem here is I tend to bind to the children property of the root elements wich returns a List of chilren. Now the children aren't really inside a view, like I can't call editview.addnew() or filter the children straight away. Question is how do I ensure the children are also in a view and their children and so on. Should the model return a view, should I create a seperate view for each children type or even for each parent?
Another thing is if I'm allowing editing should I put the Collections straight into a IEditableCollectionView or wrap it in ICollectionView first (why is that better)?
Is there a good guide to using views that isn't just pure basics?

Resources