У меня есть БД SQL Server со следующими таблицами и связями:
Работа, которая содержит много сессий.
Сессии, которые содержат много перерывов.
Прежде всего, не пугайтесь большого количества кода, размещенного здесь. Соответствующими частями являются выделенные части, относящиеся к списку, остальные только для сравнения, чтобы увидеть, где я иду не так.
В XAML я пытаюсь и преуспеваю при привязке заданий. Я получаю это, чтобы отфильтровать правильные сессии. Там нет проблем.
Моя проблема в том, что когда я пытаюсь заставить его фильтровать разрывы, принадлежащие каждому сеансу, это не сработает, но я использую все те же принципы.
Я не использую (и не заинтересован в использовании) Linq2Sql, поскольку он создает слишком много дополнительных классов, которые раздувают мой код. Я просто использую прямую привязку данных.
Я уже задавал этот вопрос и опубликовал код, но я так и не получил ответа, потому что код был слишком длинным, чтобы его можно было прочитать в разумные сроки.
Мой вопрос здесь: что я делаю не так? У меня сложилось впечатление, что, поскольку я могу успешно связывать и фильтровать сеансы, я должен иметь возможность делать то же самое с сеансами и перерывами фильтров. Но это не работает.
Я немного отчаиваюсь за помощью и оцениваю любые ответы.
РЕДАКТИРОВАТЬ: еще раз я включил примеры кода. Я не пытаюсь скрыть код для секретности и авторских прав. Это всего лишь упражнение, которое я делаю, чтобы учиться, поэтому я не возражаю опубликовать полный код. Но это очень долго. Поэтому я просто опубликую те части, которые я считаю актуальными. Если хочешь большего, просто спроси.
Для тех из вас, кто заинтересован в том, чтобы перейти к хорошей части, где есть проблемы, загляните под часть списка «Перерывы». Остальное просто для сравнения, чтобы помочь вам отладить. Ниже приведен также код C #, который поможет вам в дальнейшем. Опять же, посмотрите на часть списка, остальное только для отладки.
Ниже приведен соответствующий XAML
<!--Jobs List box - Works fine-->
<ListBox Name="lstJobs" DockPanel.Dock="Top"
MinWidth="150" MinHeight="200" MaxHeight="250"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionChanged="lstJobs_SelectionChanged"
IsSynchronizedWithCurrentItem="True"
DataContext="{Binding Tables[JobDetails]}"
ItemsSource="{Binding}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal" Margin="3,0,3,0">
<TextBlock Text="{Binding Path=Title}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding Path=ID}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--How Jobs listbox is bound to relevant fields in jobs table. This works fine-->
<TextBox Text="{Binding ElementName=lstJobs, Path=SelectedItem.ID, UpdateSourceTrigger=PropertyChanged}" Name="txtJobNo" Grid.Row="1" IsEnabled="False"/>
<TextBox Text="{Binding ElementName=lstJobs, Path=SelectedItem.Title, UpdateSourceTrigger=PropertyChanged}" Name="txtJobTitle" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"/>
<TextBox Text="{Binding ElementName=lstJobs, Path=SelectedItem.Description, UpdateSourceTrigger=PropertyChanged}" Name="txtJobDesc" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Grid.RowSpan="2"/>
<!--Sessions List box, Automatically filtered based on relationship (see last binding line). This works fine too-->
<ListBox Name="lstSessions" DockPanel.Dock="Top" MinWidth="150"
MinHeight="200" MaxHeight="220"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionChanged="lstSessions_SelectionChanged"
IsSynchronizedWithCurrentItem="True"
DataContext="{Binding Path=Tables[JobDetails]}"
ItemsSource="{Binding Path=relJobDetailsSessionDetails}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal" Margin="3,0,3,0">
<TextBlock Text="{Binding Path=Title}" />
<TextBlock Text="{Binding Path=ID}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--How Sessions listbox is bound to relevant fields in Sessions table. This works fine-->
<TextBox Name="txtSessionNo" Text="{Binding ElementName=lstSessions, Path=SelectedItem.ID, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="0"/>
<TextBox Name="txtSessionTitle" Text="{Binding ElementName=lstSessions, Path=SelectedItem.Title, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3"/>
<TextBox Name="txtSessionDesc" Text="{Binding ElementName=lstSessions, Path=SelectedItem.Description, UpdateSourceTrigger=PropertyChanged}" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Grid.RowSpan="2"/>
<!--Breaks List box, Should be automatically filtered (it is), but it does not change when a job or session is selected. Why?? -->
<ListBox Name="lstBreaks" MinWidth="150" MinHeight="140" MaxHeight="140"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionChanged="lstBreaks_SelectionChanged"
IsSynchronizedWithCurrentItem="True"
DataContext="{Binding Path=Tables[SessionDetails]}"
ItemsSource="{Binding Path=relSessionDetailsBreakDetails}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal" Margin="3,0,3,0">
<TextBlock Text="{Binding Path=Title}" />
<TextBlock Text="{Binding Path=ID}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--How Breaks listbox is bound to relevant fields in Breaks table. This works fine as before-->
<TextBox Name="txtBreakNo" Text="{Binding ElementName=lstBreaks, Path=SelectedItem.ID, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="0"/>
<TextBox Name="txtBreakTitle" Text="{Binding ElementName=lstBreaks, Path=SelectedItem.Title, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"/>
<ComboBox Name="cbxBreakType" Text="{Binding ElementName=lstBreaks, Path=SelectedItem.Description, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="3"/>
Ниже приведен код C # (опять же, выделенная часть - это разрывы, а остальное - просто для сравнения, поэтому вы можете сразу перейти к этому, если хотите):
//Connection String
string conString = "XYZ Works ok, no prob here";
//Data Adaptors for various tables
SqlDataAdapter daJobDetails = new SqlDataAdapter();
SqlDataAdapter daSessionDetails = new SqlDataAdapter();
SqlDataAdapter daBreakDetails = new SqlDataAdapter();
//The dataset to hold all of the data
DataSet dsDataSet = new DataSet();
//Step 1: Create Connection
SqlConnection conn = new SqlConnection(conString);
//Open Connection
conn.Open();
//Load Job Details Table - works fine.
daJobDetails.SelectCommand = new SqlCommand("Select * From JobDetails", conn);
daJobDetails.Fill(dsDataSet, "JobDetails");
//Load Session Details table - works fine.
daSessionDetails.SelectCommand = new SqlCommand("SELECT * FROM SessionDetails", conn);
daSessionDetails.Fill(dsDataSet, "SessionDetails");
//Relation: JobDetails.ID = SessionDetails.JobID. - Works fine
dsDataSet.Relations.Add("relJobDetailsSessionDetails",
dsDataSet.Tables["JobDetails"].Columns["ID"],
dsDataSet.Tables["SessionDetails"].Columns["JobID"]);
//**** Possible problem code *****
//Load Break Details table - could there be something wrong here.
daBreakDetails.SelectCommand = new SqlCommand("SELECT * FROM BreakDetails", conn);
daBreakDetails.Fill(dsDataSet, "BreakDetails");
//**** Possible problem code *****
//Relation: SessionDetails.ID = BreakDetails.SessionID - Could there be something wrong here
dsDataSet.Relations.Add("relSessionDetailsBreakDetails",
dsDataSet.Tables["SessionDetails"].Columns["ID"],
dsDataSet.Tables["BreakDetails"].Columns["SessionID"]);
//Set the DataContext to the DataSet
expJobs.DataContext = dsDataSet;
//Close connection
conn.Close();