Binding a wpf list to a dataset .... Maybe ..?

I tried to move to Wpf, I just got stuck while testing data binding to lsitview. I want to bind a list to a dataset (a dataset because the data that I want to display in columns refers to different tables). I am adding sample code that I am trying to use. It works well, but listliew shows only one line. What could be wrong. Can anyone guide me through. All available samples use datatables.None indicates binding to dataset.Pls help .. any input would be much appreciated ... thanks in advance

My xaml

<Grid> <TextBox Text="" Height="20" Width="100" HorizontalAlignment="Left" Margin="15,13,0,0" VerticalAlignment="Top"></TextBox> <TextBox Text="" Height="20" Width="100" HorizontalAlignment="Left" Margin="15,42,0,0" VerticalAlignment="Top"></TextBox> <ListView Margin="15,89,63,73" Name="lst" ItemsSource="{Binding}"> <ListView.View> <GridView> <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=T1/Name}"></GridViewColumn> <GridViewColumn Header="Place" DisplayMemberBinding="{Binding Path=T2/Name}"></GridViewColumn> </GridView> </ListView.View> </ListView> <!--<Button Height="19" HorizontalAlignment="Right" Name="button2" VerticalAlignment="Top" Width="46" Margin="0,42,63,0" Click="button2_Click">Add</Button>--> <Button Height="19" HorizontalAlignment="Right" Name="button1" VerticalAlignment="Top" Width="46" Click="button1_Click" Margin="0,43,63,0">Add</Button> 

My code

  Dt1 = new DataTable("T1"); Dt1.Columns.Add("Name"); Dt1.Rows.Add("abc1"); Dt1.Rows.Add("abc2"); Dt2 = new DataTable("T2"); Dt2.Columns.Add("Name"); Dt2.Rows.Add("xyz1"); Dt2.Rows.Add("xyz1"); Ds = new DataSet(); Ds.Tables.Add(Dt1); Ds.Tables.Add(Dt2); lst.DataContext = Ds; 
+4
source share
4 answers
Hi, I am in full agreement with Andy and Thomas. They both explained the concept elegantly.

I show only those steps that do the same with a dataset only.

MVVM (ModelView ViewModel) I am not discussing here.

Xaml looks like this:

 <Grid Name="myGrid" ShowGridLines="False"> <Label Height="28" Margin="12,5,0,0" Name="lblName" VerticalAlignment="Top" HorizontalAlignment="Left" Width="55">Name</Label> <TextBox Height="23" Margin="73,8,85,0" Name="txtName" VerticalAlignment="Top" /> <Label Height="28" Margin="12,39,0,0" Name="lblPlace" VerticalAlignment="Top" HorizontalAlignment="Left" Width="55">Place</Label> <TextBox Height="23" Margin="73,44,85,0" Name="txtPlace" VerticalAlignment="Top" /> <Button Height="23" HorizontalAlignment="Left" Margin="20,82,0,0" Name="btnAddRecord" VerticalAlignment="Top" Width="75" Click="btnAddRecord_Click">Add Record</Button> <ListView Margin="31,119,27,45" Name="listView" *ItemsSource="{Binding}"*> <ListView.View> <GridView> <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/> <GridViewColumn Header="Place" DisplayMemberBinding="{Binding Place}"/> </GridView> </ListView.View> </ListView> </Grid> 

Create a dataset in a .CS file

 private DataSet MyDataSet() { DataTable dtInformation1 = new DataTable(); dtInformation1.Columns.Add("Name"); dtInformation1.Columns.Add("Place"); dtInformation1.Rows.Add(txtName.Text, txtPlace.Text); DataTable dtInformation2 = new DataTable(); dtInformation2.Columns.Add("Name"); dtInformation2.Columns.Add("Place"); dtInformation2.Rows.Add(txtName.Text + "2", txtPlace.Text + "2"); DataSet Ds = new DataSet(); Ds.Tables.Add(dtInformation1); Ds.Tables.Add(dtInformation2); return Ds; } 

Next, in the click Button event, write the following

private void btnAddRecord_Click (object sender, RoutedEventArgs e)

  { **listView.ItemsSource = MyDataSet().Tables[0].DefaultView; - OR - listView.ItemsSource = MyDataSet().Tables[1].DefaultView;** } 

NB ~ You cannot assign a ListView source to a dataset.

Why? You can ask? A data set, in simple words, is a set of data tables.

Suppose you have 5 different data types. And say that none of their column names, nor the column numbers match.

Now you have assigned all this data to your data set. How does the source of control know which source it should bind?

To overcome this situation, either create a custom data type that will have all the columns of these discrete data and assign values ​​to this custom one, and then bind it to the source.

Or you need to explicitly specify the data type in the data source

But I always prefer to use the MVVM pattern for this kind of operation.

+4
source

I'm not sure what you are trying to do here ... Is this the result you expect?

 abc1 xyz1 abc2 xyz2 

There is no relationship between your tables, so the binding system cannot figure out which row of T1 you want to associate with which row of T2 ... You must either put all the data in one table or use DataRelation between two tables (but this will require additional fields ) Then you should set the DataTable as an ItemsSource, not a DataSet.

Alternatively, you can create a dedicated class for storing data, as Andy suggests.

+2
source

WPF binding disconnects from properties. For example, consider the following Person object:

 class Person { public string FirstName { get; set; } public string LastName { get; set; } } 

You can then modify the XAML for your ListView to display a collection of Person objects by doing the following:

 <ListView Margin="15,89,63,73" Name="lst" ItemsSource="{Binding}"> <ListView.View> <GridView> <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding Path=FirstName}" /> <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding Path=LastName}" /> </GridView> </ListView.View> </ListView> 

This will display the name of the object in the first column and their last name in the second column (assuming that the DataContext ListView is a collection of Person objects).

In theory, to bind values ​​in a DataTable to a ListView , you can set the ItemsSource to the DataTable Rows property. The problem is that the DataRow class does not provide properties for its columns - there is only the Item property, which takes an argument that defines the row. As far as I know, XAML does not support properties that take arguments, so I don’t think that you can use a DataTable as an ItemsSource for a ListView .

You have other options. You can create a strongly typed DataSet that will expose a DataTable with a property for each column. You can then bind each GridViewColumn to the correct property.

Another approach would be to not use a DataTable at all. Your data layer will still load data from your source into a DataTable , but then it converts that data into regular objects. You can create an instance of an ObservableCollection , add each of the objects to it, and then bind a ListView to it. Each GridViewColumn simply bound to the corresponding property of the objects.

Updated:

In response to a further OP question:

Can xsd be used for this purpose? contains a property for each data type.

You need more than just a property for a DataTable. You will also need a property for each value in each row of the DataTable. Otherwise, no property exists for the ListView columns for the binding.

+1
source

It worked for me.

 public partial class MainWindow : Window { public ObservableCollection<DataTable> _observableCollection = new ObservableCollection<DataTable>(); public MainWindow() { InitializeComponent(); DataTable dt1 = new DataTable(); dt1.Columns.Add("OrderID"); dt1.Columns.Add("CustomerID"); dt1.Columns.Add("ProductID"); dt1.Rows.Add("test1", "test2", "test3"); DataTable dt2 = new DataTable(); dt2.Columns.Add("OrderID"); dt2.Columns.Add("CustomerID"); dt2.Columns.Add("ProductID"); dt2.Rows.Add("test4", "test5", "test6"); _observableCollection.Add(dtInformation1); _observableCollection.Add(dtInformation2); } public ObservableCollection<DataTable> _Collection { get { return _observableCollection; } } 

Listview xaml

 <ListView Height="Auto" HorizontalAlignment="Stretch" Name="somename" ItemsSource="{Binding _Collection}" VerticalAlignment="Stretch" Width="Auto" > 

  <GridViewColumn Header="OrderID" Width="auto" > <GridViewColumn.CellTemplate> <DataTemplate> <Button Tag="{Binding OrderID}" Content="{Binding OrderID}"/> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn Width="auto" DisplayMemberBinding="{Binding CustomerID}" Header="CustomerID" /> <GridViewColumn Width="auto" DisplayMemberBinding="{Binding ProductID}" Header="ProductID" /> 

+1
source

Source: https://habr.com/ru/post/1285865/


All Articles