У меня есть wpf TabControl
и ListBox
. Если я нажму на один из элементов в ListBox
, я хочу получить данные из определенной таблицы на SQL Server, добавлю новую вкладку в TabControl
и отобразлю данные в DataGrid
на этой новой вкладке. Пока у меня это:
XAML для TabControl
и 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>
Моя модель просмотра:
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");
}
}
}
}
Событие клика для 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
}
}
Теперь происходит то, что когда я нажимаю на один из элементов в ListBox
, правильно создается новая вкладка с текстом выбранного элемента ListBox
в качестве заголовка, а также DataGrid
, однако DataGrid
остается пустым.
Было бы действительно удивительно, если бы вы могли мне помочь. Я просмотрел все подобные вопросы здесь, на SO, но ни одно из решений, похоже, не решает мою проблему. Если я не использую элемент управления вкладками и просто добавляю DataGrid
прямо в форму, все работает отлично. Также создание и добавление всего непосредственно в код работает нормально, но я хотел бы решить это более правильным способом.
извините, это осталось от более ранней версии кода, где у меня была только одна таблица данных... Я исправил код выше.
SelectedTables
должен возвращать IEnumerable<T>
, где тип T
определяет имя а такжеDataTable
для текущей вкладки:
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");
}
}
}
}
Затем вы должны добавить новый T
(названный TabViewModel
в приведенном выше примере кода) к MainViewModel
в вашем методе opendata
:
string tabletoload = lb.SelectedItem.ToString();
myview2.SelectedTables.Add(new TabViewModel() { Header = tabletoload, Tablecontent = mydata });
... и определите ItemTemplate
для TabControl
в представлении, чтобы отобразить заголовок:
<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>
Большое спасибо, теперь это работает! Подводя итог для моего понимания: проблема заключалась в том, что я хранил заголовки и содержимое (таблицы данных) в двух отдельных наблюдаемых коллекциях, а не в одном объекте, верно?
@dunkleosteus: Да.
Что такое "DefaultView"? ObservableCollection Tablecontent не содержит этого свойства.