Reputation: 336
I have a wpf TabControl
and a ListBox
. If I click on one of the items in the ListBox
I want to get data from a certain table on an SQL Server, add a new tab to the TabControl
and display the data on a DataGrid
on this new tab. So far I have this:
XAML for the TabControl
and the ListBox
:
<Grid>
<ListBox x:Name="lb" ItemsSource="{Binding Alltables}" MouseDoubleClick="opendata"/>
<TabControl x:Name="tabControl" ItemsSource="{Binding SelectedTables}">
<TabControl.ContentTemplate >
<DataTemplate >
<Grid>
<DataGrid x:Name="dataGrid" AutoGenerateColumns="True" ItemsSource="{Binding Tablecontent}"/>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
My ViewModel:
public class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
private ObservableCollection<String> selectedtables;
public ObservableCollection<String> SelectedTables
{
get { return selectedtables; }
set
{
if (selectedtables != value)
{
selectedtables = value;
OnPropertyChanged("SelectedTables");
}
}
}
private ObservableCollection<DataTable> tablecontent;
public ObservableCollection<DataTable> Tablecontent
{
get { return tablecontent; }
set
{
if (tablecontent != value)
{
tablecontent = value;
OnPropertyChanged("Tablecontent");
}
}
}
}
The click event for the ListBox
:
private void opendata(object sender, MouseButtonEventArgs e)
{
//...
//Some preparations before querying the data etc.
//...
DataTable mydata = new DataTable();
using (connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Connection.Open();
SqlDataReader reader = command.ExecuteReader();
mydata.Load(reader);
}
string tabletoload = lb.SelectedItem.ToString();
myview2.SelectedTables.Add(tabletoload); //myview2 is the instance of my ViewModel
myview2.Tablecontent.Add(mydata); //myview2 is the instance of my ViewModel
}
}
What happens now is that when I click on one of the items in the ListBox
there is correctly a new tab created with the text of the selected ListBox
Item as Header and also a DataGrid
- however the DataGrid
remains empty.
Would be really amazing if you could help me. I have looked through all the similar questions here on SO but none of the solutions seems to solve my issue. If I don't use a tab control and simply add a DataGrid
directly on the form everything works perfectly. Also creating and adding everything directly in code works fine but I would like to solve this in a more correct way.
Upvotes: 1
Views: 320
Reputation: 169200
SelectedTables
should return an IEnumerable<T>
where the type T
defines the name and the DataTable
for the current tab:
public class TabViewModel
{
public string Header { get; set; }
public DataTable Tablecontent { get; set; }
}
public class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
private ObservableCollection<TabViewModel> selectedtables;
public ObservableCollection<TabViewModel> SelectedTables
{
get { return selectedtables; }
set
{
if (selectedtables != value)
{
selectedtables = value;
OnPropertyChanged("SelectedTables");
}
}
}
}
You would then add a new T
(named TabViewModel
in the sample code above) to the MainViewModel
in your opendata
method:
string tabletoload = lb.SelectedItem.ToString();
myview2.SelectedTables.Add(new TabViewModel() { Header = tabletoload, Tablecontent = mydata });
...and define an ItemTemplate
for the TabControl
in the view to display the header:
<TabControl x:Name="tabControl" ItemsSource="{Binding SelectedTables}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate >
<DataTemplate >
<Grid>
<DataGrid x:Name="dataGrid" AutoGenerateColumns="True" ItemsSource="{Binding Tablecontent}"/>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Upvotes: 2