4
votes

I have the following tables:

Company {CompanyID, CompanyName}
Deal {CompanyID, Value}

And I have a listbox:

<ListBox Name="Deals"
         Height="100" Width="420" Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"
         Visibility="Visible" IsSynchronizedWithCurrentItem="True"
         ItemsSource="{Binding}" SelectionChanged="Deals_SelectionChanged">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding companyRowByBuyFromCompanyFK.CompanyName}" FontWeight="Bold"  />
                <TextBlock Text=" -> TGS -> " />
                <TextBlock Text="{Binding BuyFrom}" FontWeight="Bold" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

As you can see, I want to display the CompanyName rather then the ID which is a foreign Key. The relation "companyRowByBuyFromCompanyFK" exists, as in Deals_SelectionChanged I can access companyRowByBuyFromCompanyFK property of the Deals row, and I also can access the CompanyName propert of that row.

Is the reason why this is not working because XAML binding uses the [] indexer? Rather than properties on the CompanyRows in my DataTable?

At the moment im getting values such as

  • -> TGS -> 3
  • -> TGS -> 4

Edit Binding Error Update

System.Windows.Data Error: 39 : BindingExpression path error: 'companyRowByBuyFromCompanyFK' property not found on 'object' ''DataRowView' (HashCode=30295189)'. BindingExpression:Path=companyRowByBuyFromCompanyFK.CompanyName; DataItem='DataRowView' (HashCode=30295189); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

Looks like its not converting the DataRowView item into a SuppliersRow

What would be the best way to accomplish this?

  1. Make a converter to convert foreign keys using Table being referenced as custom parameter.

  2. Create Table View for each table? This would be long winded as I have quite a large number of tables that have foreign keys.

2
If you add a trace to your binding: {Binding Path=companyRowByBuyFromCompanyFK.CompanyName, diagnostics:PresentationTraceSources.TraceLevel=High} and watch your output window when the listbox binds, what does it say? That might give us some more insight into what's failing in the binding.E.Z. Hart
Omg thanks for that! I always forget the output window!!!! Wwhy dont it show up in the errors window!! I fixed it now :) thanks for the tip tho!!!Michal Ciechan

2 Answers

2
votes

Somebody kill me.... thanks for pointing out the output window I always forget about that! :(

I found the solution by looking at the output window which was the following

System.Windows.Data Error: 39 : BindingExpression path error: 'companyRowByBuyFromCompanyFK' property not found on 'object' ''DataRowView

I figured out that the DataTemplate binding was binding to the SelectedItem of the DataTemplate which is a DataRowView and not the actual strong typed data. Luckily the DataRowView class has a Row property pointing to the DataRow (which is the supplierRow) class therefore I could bind from there as normal. Fix was in the followign line.

<TextBlock Text="{Binding companyRowByBuyFromCompanyFK.CompanyName}" FontWeight="Bold"  />

Changing this to the following worked as I expected it to.

<TextBlock Text="{Binding Row.companyRowByBuyFromCompanyFK.CompanyName}" FontWeight="Bold"  />
1
votes

How about setting a multibinding in the datatemplate that converts the row (the datasource from the listitem), together with a hierarchical binding (that passes the reference to the other table from the parent control) and the name of the field in the other table to search for the id within?

<UserControl x:Class="local:MyUserControl">
    <ListBox ItemsSource="{Binding Items}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Label>
                    <Label.Content>
                        <MultiBinding Converter="{StaticResource myConverter}">
                            <Binding Path="OtherId" />
                            <Binding
                                RelativeSource="RelativeSource FindAncestor,
                                    AncestorType={x:Type local:MyUserControl}}}"
                                Path="OtherTable" />
                        </MultiBinding>
                    </Label.Content>
                </Label>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</UserControl>

In the converter:

public object Convert(object[] values, Type targetType, object parameter,
    System.Globalization.CultureInfo culture)
{
    // TODO: Input type checks

    // TODO: Castings, find key in other table, return relevant field
    return (values[1] as IDictionary<String, String>)[values[0] as String];
}