Is there a simple way of binding to parent rows in WPF?
I'm fairly new to VB.net and WPF (and programming in general), so please bear with me. I'm attempting to write a useful database app for my business as a learning project. I did a draft in WinForms, referring to the (very good) Murach book, but am now trying to re-write it with a WPF UI and cleaner code.
I think I understand the basics of WPF binding, but am tearing my hair out trying to find a simple way of binding to parent details - which I would have thought was a very basic scenario, but I can't find anything on it. For example, let's say I have
- a 'Customers' table with CustomerID, Name, various contact details and then foreign keys CityID and GroupID;
- a 'City' table with CityID, CityName and foreign key StateID;
- a 'State' table with StateID, StateName;
- a 'Groups' table with GroupID, GroupName etc.
...with a strongly typed dataset including relationships and a bunch of tableadapters.
All I want to do in this case is display the details for a specific Customer (when the user has entered their CustomerID). I can easily bind to the data in the 'Customers' table, but how do I use bindings to retrieve the CityName, StateName and GroupName from the related tables? A partial example below.
...
<Window.Resources>
<CollectionViewSource x:Key="CustomersViewSource"
Source="{Binding Path=Customers,Source={StaticResource CustomersDataSet}}" />
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource CustomersViewSource}}">
<TextBox Name="customerName" Text="{Binding Path=Name}" />
<TextBox Name="customerPhone" Text="{Binding Path=PhoneNumber}" />
</Grid>
<Grid>
<Label Name="lblGroup" Content="[needs to bind to GroupName]">
<Label Name="lblCity" Content="[needs to bind to CityName]">
</Grid>
I've read articles on setting up master/detail scenarios, which is straightforward, so I could bind customers into a datagrid for a selected city, for example, by using the foreign key as the binding path for the customer control. Here I'm trying to do it back the other way, though, looking up the parent details based on a selected customer. Can anyone nudge me in the right direction?
Failing this, I've only been able to do it through VB - and it's pretty nasty. Assuming that I've created a CustomerViewSource and looked up the relevant customer, and filled the various tables in my dataset, something like this:
Dim rowCustomer As System.Data.DataRowView = CustomerViewSource.View.CurrentItem
Dim drCustomer As System.Data.Datarow = rowCustomer.Row
Dim drGroup as drCustomer.GetParentRow("FK_Customers_Groups")
lblGroup.Content = drGroup.Item("GroupName")
I shouldn't have to do this so clumsily though... should I?
One more th开发者_StackOverflow社区ing: at the moment I'm selecting a customer by filling the dataset using a parameterized query on the tableadapter, e.g.
SELECT CustomerID, CustomerName
FROM Customers
WHERE CustomerID = @CustomerID
And then just moving to the first record (as there will only be one). Is this a normal method of looking up a customer? I could also use this method by getting the foreign keys from my customer row and filling the different tables in the dataset all using parameterised queries, then just binding to each table separately - but again, seems very messy.
Any help with this problem, or even general advice, hugely appreciated. If I haven't been clear enough (or provided good examples), happy to explain further. Cheers.
First, these are actually child rows, not parent rows. It's a little counterintuitive, but the parent is the "one" side of the one-to-many relation, and the child is the "many," so Group, City, and State are all parents of Customer. Your code example shows this.
Next, in ADO.NET, you can accomplish everything you're trying to do here by creating a DataColumn
in the Customer DataTable
and setting its Expression. Create a column named StateName
and set its expression to Parent(FK_Customers_States).StateName
. Now you can bind to it the way you'd bind to any other column.
精彩评论