-1

I have 2 tables, table A and table B. I want to have a listBox with data from both tables like this:

 <ListBox.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Path=[field_name]}"/>
      </StackPanel>
     </DataTemplate>
 </ListBox.ItemTemplate>

where field_name will be first A.someFieldName and then B.someOtherFieldName (both names are different!)

is it possible using WPF?

Thank you!

Maya Saias
  • 37
  • 9
  • Technically you could have two columns in a ListBox. But it is probably a better idea to use a ListView instead: https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/listview-overview?view=netframeworkdesktop-4.8 – PEK Jul 25 '21 at 17:52
  • Do you want to use two tables as a data source? That is not possible. You have to combine these tables first before you use them as a data source. – PEK Jul 25 '21 at 17:54
  • There's this thing called MultiBinding, but whether it's a good idea to solve your case... depends on what you're doing. Not sure it can work for lists at all. https://stackoverflow.com/questions/2552853/how-to-bind-multiple-values-to-a-single-wpf-textblock – Bent Tranberg Jul 25 '21 at 17:56
  • 2
    @PEK that is possible, with usage of composite collection. – XAMlMAX Jul 25 '21 at 21:22

1 Answers1

1

You could add two DataTemplate resources, one for each type A and B, without x:Key, just DataType so they're used implicitly as default templates. The dual collection thing can be handled by a CompositeCollection.

This is how it'd work schematically:

<ListBox>
        <ListBox.Resources>
            <CollectionViewSource x:Key="ListOfA" Source="{Binding ListOfA}"/>
            <CollectionViewSource x:Key="ListOfB" Source="{Binding ListOfB}"/>
            <DataTemplate DataType="{x:Type local:A}">
                <TextBlock Text="{Binding Path=Name }"/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type local:B}">
                <TextBlock Text="{Binding Path=Value}"/>
            </DataTemplate>
        </ListBox.Resources>
        <ListBox.ItemsSource>
            <CompositeCollection>
                <CollectionContainer Collection="{Binding Source={StaticResource ListOfA}}" />
                <CollectionContainer Collection="{Binding Source={StaticResource ListOfB}}" />
            </CompositeCollection>
        </ListBox.ItemsSource>
    </ListBox>

ViewModel (just for the Demo) => DataContext of the ListBox

public class MainViewModel
    {
        public MainViewModel (){
            ListOfA = new List<A> { new A { Name  = "Susi" }, new A { Name = "Bertie" }, new A { Name = "Anna" } };
            ListOfB = new List<B> { new B { Value = 600 }, new B { Value   = 700 }, new B { Value     = 1000 } };
        }

        public List<A> ListOfA { get; }
        public List<B> ListOfB { get; }
    }

    public class A
    {
        public string Name { get; set;}
    }
    public class B
    {
        public int Value { get; set; }
    }
lidqy
  • 1,891
  • 1
  • 9
  • 11
  • I have been tryingt to follow your answer but I am having a hard time fitting it to my case. My 2 lists are taken from db (Oracle sql) and each of them is a list of DataRows. So for now if I have 2 seperate ListBox I bind them using {Binding Path=["A"]} where A is the name of some row in the db – Maya Saias Aug 02 '21 at 17:20
  • If both lists are of the same type (`DataRow`) it doesn't work like in my example. You could still use a `ItemTemplateSelector` to serve one template for each list. As a starter this link might be helpful..: https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.itemscontrol.itemtemplateselector?view=net-5.0 I don't know if this is easy to understand. An Item template selector analyzes the data for each "item" aka row. According to the items data it returns itemtemplate A or B (or C). Its up to you to define the switch / criteria. – lidqy Aug 02 '21 at 21:57