I have a tabcontrol, each item of this tabcontrol is made with some label.
I insert manually all the information in the different label but I want to bind the information I think is more clean.
I have an entity BE this is the data that I want to bien
this is my code:
numBe.Content = BE.BE_Numero_BE;
BeDate.Content = BE.BE_Date;
Numcarnet.Content = BE.BE_Numero_carnet;
BeFourn.Content = BE.BE_Fournisseur;
BECom.Content = BE.BE_Commercial;
NumTicket.Content = BE.BE_Numero_ticket;
NumCnt.Content = BE.BE_Numero_carnet;
TypeBe.Content = BE.BE_Type_BE;
BeImm.Content = BE.BE_Immatriculation;
BeSC.Content = BE.BE_Stock_client;
NumS.Content = BE.BE_N_serie;
BeSa.Content = BE.BE_SA;
BeEx.Content = BE.BE_Exutoire;
BeNrcde.Content = BE.BE_NrCde;
I already do this but I don't know how to bind :
<TabControl x:Name="TabControlBe" HorizontalAlignment="Left" Margin="17,425,0,0" Grid.Row="1" Width="471" >
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock>BE1</TextBlock>
</StackPanel>
</TabItem.Header>
<Grid>
<Label Content="Numero Be:" Height="27" VerticalAlignment="Top" HorizontalAlignment="Left" Width="75"/>
<Label x:Name="numBe" Content="{Binding BE_Numero}" Height="25" Margin="0,0,50,0" HorizontalAlignment="Right" Width="331" VerticalAlignment="Top" />...
Thanks for your help
Related
I use an observableCollecion in my VM. This Collection is bind into my view in a ListView. In my items I try to get the element who create this item. Add it in my commandParameter and do the thing.
Here's my VM :
public RelayCommand<SelectionCommandParameter> CmdRemoveFromQuiz { get; set; }
public ObservableCollection<Question> SelectedQuiz
{
get { return _selectedQuiz; }
set
{
_selectedQuiz = value;
RaisePropertyChanged("SelectedQuiz");
}
}
private void RemoveFromQuiz(SelectionCommandParameter selection)
{
if (selection.Parameter is Question)
{
ObservableCollection<Question> tempQuiz = SelectedQuiz;
Question _question = (Question)selection.Parameter;
tempQuiz.Remove(_question);
SelectedQuiz = tempQuiz;
}
}
The problem start with the RemoveBtn I start the command, and selection stay null I want to get the ObservableCollection<Question> object use in my ListViewitem
Now My View :
<userControls:CharmFlyout
x:Name="cfoQuizList"
x:Uid="QuizListCreatingPageFlyout"
Heading="Question Multiple"
HorizontalAlignment="Left"
Grid.Column="0"
Grid.RowSpan="2"
Style="{StaticResource stlAddRecipientFlyout}">
<tut:TutorialAwareListView x:Name="gvQuizItem"
ItemsSource="{Binding SelectedQuiz}"
IsItemClickEnabled="True"
CanReorderItems="True"
SelectionMode="None"
ManipulationMode="TranslateRailsX">
<ListView.ItemTemplate>
<DataTemplate x:Name="DTQuizItem">
<Grid HorizontalAlignment="Left" Width="{StaticResource RectangleTileWidth}" Height="{StaticResource RectangleTileHeight}"
Margin="0 0 0 0" Background="{StaticResource OrangeBackgroundThemeBrush}">
<Grid Grid.Column="1">
<Button x:Name="RemoveBtn" Content="X" HorizontalAlignment="Right" VerticalAlignment="Top" Width="40" Height="40"
BorderThickness="0" Command="{Binding DataContext.CmdRemoveFromQuiz, ElementName=gvQuizItem}" CommandParameter="{Binding Question}"/>
<maxCtrls:MaxAutoScrollingContentPresenter VerticalAlignment="Center"
ScrollingDuration="{Binding Name, Converter={StaticResource TextToTimeToReadShortFormatConverter}}"
ScrollingBeginTime="0:0:2">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold"
Foreground="{StaticResource WhiteBackground}"
Margin="20,5,10,5" VerticalAlignment="Center" TextWrapping="Wrap"/>
</maxCtrls:MaxAutoScrollingContentPresenter>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</tut:TutorialAwareListView>
</userControls:CharmFlyout>
The TutorialAwareListView Work exactly like a ListView. I use it juste to point the element while the tutorial is running.
It's a Windows Store App !! I can't do all the thing we would like to.
You should change your SelectionMode="None" to Single or Multiply.
And make new ObservableCollection for selected items. You bind just ItemsSource="{Binding SelectedQuiz}". Bind SelectedItems="{...}"
I have a DataGrid and fill it with a DataTable.
dgMitarbeiter.ItemsSource = mainController.loadDataTableMitarbeiter().DefaultView;
this is the function:
public DataTable loadDataTableMitarbeiter()
{
loadMitarbeiterList();
dtMitarbeiter.Clear();
foreach (Mitarbeiter mitarbeiter in mitarbeiterList)
{
drMitarbeiter = dtMitarbeiter.NewRow();
drMitarbeiter["ID"] = mitarbeiter.ID;
drMitarbeiter["Vorname"] = mitarbeiter.vorname;
drMitarbeiter["Nachname"] = mitarbeiter.nachname;
drMitarbeiter["Kostenstelle"] = mitarbeiter.kostenstelle.id;
drMitarbeiter["Größe Hose"] = mitarbeiter.gr_hose;
drMitarbeiter["Größe Oberteil"] = mitarbeiter.gr_oberteil;
drMitarbeiter["Gröse Schuhe"] = mitarbeiter.gr_schuhe;
drMitarbeiter["Ferial"] = mitarbeiter.ferial;
drMitarbeiter["Werk"] = mitarbeiter.werk;
drMitarbeiter["Datum"] = mitarbeiter.creationDate.ToString("dd.MM.yyyy");
dtMitarbeiter.Rows.Add(drMitarbeiter);
}
return dtMitarbeiter;
}
The Xaml:
<DataGrid x:Name="dgMitarbeiter" AlternatingRowBackground="Gainsboro" AlternationCount="2" ColumnWidth="*" HorizontalAlignment="Left" SelectedItem="{Binding SelectedItem}" Margin="10,22,0,0" VerticalAlignment="Top" Height="357" Width="731" CanUserAddRows="False" CanUserDeleteRows="False" RowEditEnding="dgMitarbeiter_RowEditEnding" Background="White" HeadersVisibility="Column"/>
I need a ComboBox for the column "Kostenstelle" but have no idea how to achieve this. Any ideas?
My answer implements an ObservableCollection. And adds this as a databinding to the ComboBox
You need a new class:
public class Kostenstellen: ObservableCollection<Kostenstelle>
{
}
And a fill Method with the following lines of code:
var kostenstellen = new Kostenstellen();
foreach mitarbeiter in mitarbeiterList
{
kostenstellen.Add(mitarbeiter.kostenstelle);
}
var cvsCombobox = new CollectionViewSource() { Source = this.operationList };
this.myCombobox.SetBinding(ItemsControl.ItemsSourceProperty, new Binding() { Source = cvsCombobox });
Now there will be only "(Kostenstelle)" as a string in the Combobox.
So you need to override the ToString() method of your Kostenstelle class
public partial class Kostenstelle
{
public override string ToString()
{
return this.ID.ToString();
}
}
HINT:
Use english variable and class names next time :)
You need to define a DataGridComboBoxColumn in your DataGrid columns, you can then bind the ItemsSource to wherever your combo box's options are located.
See here.
You can do a lot in your xaml file :) For myself I used this one lately...
In the xaml file you can now define the placement of the combobox on your page.
you can set the content by code later.
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Items In Group"
TabIndex="1"
Grid.RowSpan="2"
Padding="120,126,120,50"
ItemsSource="{Binding}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"
>
<GridView.ItemTemplate >
<DataTemplate >
<Grid Height="150" Width="480" Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,10,0,0" >
<TextBlock Text="{Binding title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" FontSize="25"/>
<Line/>
<TextBlock Text="{Binding subtitle}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" FontSize="20" Margin="0,10,0,0" />
<Line/>
<TextBlock Text="{Binding description}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" FontSize="15" Margin="0,10,0,0"/>
<Button Tag="{Binding title}" Click="ItemButtonClicked" Content="Details" FontSize="15" Margin="0,10,0,0"/>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemContainerStyle>
<Style TargetType="FrameworkElement" >
<Setter Property="Margin" Value="52,0,0,2"/>
</Style>
</GridView.ItemContainerStyle>
</GridView>
Requirement:-
Want to show the contact list with alphabets groups.
Using Long list selector displays the contacts list. In xaml, we mention the IsFlatList="false" in long list selector for grouping, but it displays the contacts list without groups like list box.
I herewith attached my code for your comments, please let me know where I did mistake in my code.
<phone:PhoneApplicationPage.Resources>
<!--Heading for the items(a,b,c,d) -->
<DataTemplate x:Key="GroupItemHeaderTemplate">
<Border Background="Transparent" Padding="5">
<Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="480" Height="40" Margin="0,0,18,0" HorizontalAlignment="Left">
<TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="20" Padding="6" FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="left" VerticalAlignment="Center"/>
</Border>
</Border>
</DataTemplate>
<!-- Heading For the list -->
<DataTemplate x:Key="ListHeader">
<Border Background="#FF049ED6" Height="40">
<TextBlock Text= "{Binding Key}" />
</Border>
</DataTemplate>
<!--Items to display-->
<DataTemplate x:Key="ItemTemplate" >
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ListImage}" Height="100" Width="100" Stretch="Uniform" Margin="10,2,0,0" ImageFailed="Image_ImageFailed" />
<TextBlock Text="{Binding ListFullName}" Width="200" Foreground="Black" Margin="10,10,0,0" FontWeight="SemiBold" FontSize="22" />
<TextBlock Text="{Binding ListBio}" FlowDirection="LeftToRight" Foreground="Black" Margin="-200,50,0,0" FontWeight="ExtraLight" FontSize="20" />
</StackPanel>
</DataTemplate>
<!--Group Intems Panel to show when click on Items Header-->
<ItemsPanelTemplate x:Key="GroupItemsPanel">
<toolkit:WrapPanel ItemHeight="105" ItemWidth="105"></toolkit:WrapPanel>
</ItemsPanelTemplate>
</phone:PhoneApplicationPage.Resources>
<toolkit:LongListSelector x:Name="LongListSelectorListBox" ItemsSource="{Binding Content}"
Margin="0,235,5,104" Width="480" Background="Transparent" IsFlatList="True"
DisplayAllGroups="False" ItemTemplate="{StaticResource ItemTemplate}"
GroupHeaderTemplate="{StaticResource GroupItemHeaderTemplate}"
ListHeaderTemplate="{StaticResource ListHeader}" GroupItemsPanel="{StaticResource GroupItemsPanel}"
SelectionChanged="LongListSelectorListBox_SelectionChanged" />
ViewModel:-
ServiceModel sm = new ServiceModel();
Content = new ObservableCollection<ListContactsModel>();
Content1 = new ObservableCollection<ListContactsModel>();
ServiceConstants.Temp_Response = x;//Save The response temp
ObservableCollection<ListContactsModel> result = ListContactsModel.extract(x, sm, OutGoingInvitation);
ObservableCollection<ListContactsModel> result1 = ListContactsModel.extract(x, sm, IncomeInvitation);
AppGlobalConstants.Temp_Response = result;
if (!((string.IsNullOrEmpty(sm.NetErrorCode)) && (string.IsNullOrEmpty(sm.ProvResErrCode))))
{
string errCode = !string.IsNullOrEmpty(sm.NetErrorCode) ? sm.NetErrorCode : sm.ProvResErrCode;
string errDesc = !string.IsNullOrEmpty(sm.NetErrorDesc) ? sm.NetErrorDesc : sm.ProvResErrDesc;
MessageBox.Show(errCode + "/" + errDesc);
}else if (result.Count > 0)
{
Content.Clear();
Content1.Clear();
Content = result;//Outgoing Invitations
Content1 = result1;//Incoming Invitations
List<AlphaKeyGroup<ListContactsModel>> DataSource = AlphaKeyGroup<ListContactsModel>.CreateGroups(result,
System.Threading.Thread.CurrentThread.CurrentUICulture,
(ListContactsModel s) => { return s.ListFullName; },
true);
Console.WriteLine("Content.Count==>>" + Content.Count);
Console.WriteLine("DataSource.ElementAt(1).Key==>>" + DataSource.ElementAt(1).Key);
Console.WriteLine("DataSource.ElementAt(2).Key==>>" + DataSource.ElementAt(2).Key);
Regards,
Naresh T
I don't see whole code and I don't know what is ListContactsModel. Is it a collection (inherits from IEnumerable/List/...)? Does it have Items propery? Does it have GetEnumerator methods?
As far as I understand AlphaKeyGroup class was taken from here (if not, read it first) http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj244365(v=vs.105).aspx
So maybe you want to bind LongListSelector to some property, that receive data from DataSource and has the same type List<_AlphaKeyGroup<ListContactsModel>_> (not to Content)?
Here is a couple of articles about LongListSelector:
http://www.geekchamp.com/articles/wp7-longlistselector-in-depth--part1-visual-structure-and-api
http://www.geekchamp.com/articles/wp7-longlistselector-in-depth--part2-data-binding-scenarios (this one will be great for you)
First of all, follow the instructions.
In general grouping in LLS means, that you have collection of items, that consist of Key/Title/Header/whatever and inner collection of group elements.
I have a gridView.
ıt has an Itemptemplate (textblock, image) and itemsource. textBlock and Image are binded to itemsource.
I want to add a button to ItempTemplate but I couldn't able to detect the eventHandler.
In my .cs file I dont see textblock, image or button.
how can I set the event,
here is the code of item template
<DataTemplate x:Key="IDViewStyle">
<Grid Width="350" Height="450" >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid>
<Border Background="#B2060606" />
<Button HorizontalAlignment="Right" BorderThickness="0" x:Name="eraseButton" VerticalAlignment="Top">
<Image Source="/Assets/Images/erease.png" Width="90" Margin="0,-7,-15,15"/>
</Button>
<StackPanel Margin="0" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="+" VerticalAlignment="Center" Style="{StaticResource PageHeaderTextStyle}" FontSize="160" Margin="0"/>
<TextBlock TextWrapping="Wrap" Text="Ekle" TextAlignment="Center" Style="{StaticResource HeaderTextStyle}"/>
</StackPanel>
<Image Stretch="Fill" Source="{Binding Image}"/>
</Grid>
<TextBlock TextWrapping="Wrap" Text="{Binding Type}" VerticalAlignment="Top" Grid.Row="1" Style="{StaticResource SubheaderTextStyle}" TextAlignment="Center"/>
</Grid>
</DataTemplate>
and my .cs file
Data.IdentityTypeCollection collection;
gView.SelectionChanged += lvIdTypes_SelectionChanged;
collection = new Data.IdentityTypeCollection();
gView.ItemsSource = collection;
gView.ScrollIntoView(collection);
and my mainpage.xaml
<GridView x:Name="gView" Grid.Row="1" Grid.RowSpan="2" Margin="117,0,0,100" ItemTemplate="{StaticResource IDViewStyle}"/>
how can I use button event in the item template
On GridView you can assign a property ItemClick="YourClickEvent" like:
<GridView
x:Name="itemGridView"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"></GridView>
and in your .cs file the event handler:
void YourClickEvent(object sender, ItemClickEventArgs e)
{
//your codes here
}
Make sure GridView IsItemClickEnabled is set to True All set!
If I understand your question then this is what I did after using the debugger to look around. This is a UWP application. The Button is in a Grid in a DataTemplate in a "MedView" GridView. The following sets the ItemsSource:
List<ViewItemClass> lvil = new List<ViewItemClass>();
// create lvil
MedView.ItemsSource = lvil;
Then I added a Click event handler for the Button and the following is the code for that:
Button b = sender as Button;
if (b == null)
return;
Grid g = b.Parent as Grid;
if (g == null)
return;
ViewItemClass lvi = g.DataContext as ViewItemClass;
if (lvi == null)
return;
// use the item
I have a SQL Server DB with the following tables and relationships:
Jobs which contains many sessions.
Sessions which contains many breaks.
First of all, dont be frightened by the large amount of code posted here. The relevant parts are the highlighted parts dealing with the list, the rest is just for comparison to see where I am going wrong.
In XAML I am trying and succeeding when binding jobs. I get it to filter out the correct sessions. No problem there.
My problem is that when I try to get it to filter the breaks that belong to each session it wont work but I am using all the same principles.
I am not using (nor interested in using) Linq2Sql as it creates too many additional classes that bloat my code. I am just using direct databinding.
I have asked this question before and posted code, but I never got any reply because the code was simply too long to read in a reasonable timeframe.
My question here is, what am I doing wrong. I was with the impression that since I can successfully bind and filter sessions, then I should be able to do likewise with sessions and filter breaks. But it doesnt work.
I am getting somewhat desparate for help and appreicate any answers.
EDIT: Once again I have included code samples. I am not trying to hide the code for secrecy and copyright. It is just an exercise I am doing to learn so I wouldnt mind posting the full code. But it is very long. So I will just post the parts I think are relevant. If you want more just ask.
For those of you interested in skipping to the good part where the problems are, look under the part of the Breaks list box. The rest is just there for comparison to help you debug. There is also C# code below to help further. Again, look at the list part the rest is just for debugging.
Below is the relevant 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"/>
Following is the C# Code behind (Once again, the highlighted part is the breaks and the rest is just for comparison, so you can skip directly to that if you like):
//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();
As requested, here is a full repro case.
Update: updated with the working code from your link. Looks like the answer was binding to SelectedItem => relation. Very logical, actually.
XAML:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*"/>
<ColumnDefinition Width=".5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height=".33*"/>
<RowDefinition Height=".33*"/>
<RowDefinition Height=".33*"/>
</Grid.RowDefinitions>
<!--Jobs List box - Works fine-->
<ListBox Name="lstJobs" Grid.Column="0" Grid.Row="0"
MinWidth="150"
MinHeight="200"
MaxHeight="250"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionChanged="lstJobs_SelectionChanged"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=JobDetails}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal" Margin="3,0,3,0">
<TextBlock Text="{Binding Path=ID}"/>
<TextBlock Text="{Binding Path=Title}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--How Jobs listbox is bound to relevant fields in jobs table. This works fine-->
<StackPanel Orientation="Vertical" Grid.Column="1" Grid.Row="0">
<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"/>
</StackPanel>
<!--Sessions List box, Automatically filtered based on relationship (see last binding line). This works fine too -->
<ListBox Name="lstSessions" Grid.Column="0" Grid.Row="1"
DockPanel.Dock="Top"
MinWidth="150"
MinHeight="200"
MaxHeight="220"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionChanged="lstSessions_SelectionChanged"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding ElementName=lstJobs, Path=SelectedItem.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-->
<StackPanel Orientation="Vertical" Grid.Column="1" Grid.Row="1">
<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"/>
</StackPanel>
<!--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" Grid.Column="0" Grid.Row="2"
MinWidth="150"
MinHeight="140"
MaxHeight="140"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionChanged="lstBreaks_SelectionChanged"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding ElementName=lstSessions, Path=SelectedItem.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-->
<StackPanel Orientation="Vertical" Grid.Column="1" Grid.Row="2">
<TextBox Name="txtBreakNo" DockPanel.Dock="Bottom"
Text="{Binding ElementName=lstBreaks, Path=SelectedItem.ID, UpdateSourceTrigger=PropertyChanged}"
Grid.Row="2" Grid.Column="1"/>
<TextBox Name="txtBreakTitle" DockPanel.Dock="Bottom"
Text="{Binding ElementName=lstBreaks, Path=SelectedItem.Title, UpdateSourceTrigger=PropertyChanged}"
Grid.Row="2" Grid.Column="2"/>
<ComboBox Name="cbxBreakType" DockPanel.Dock="Bottom"
Text="{Binding ElementName=lstBreaks, Path=SelectedItem.Description, UpdateSourceTrigger=PropertyChanged}"
Grid.Row="2" Grid.Column="3"/>
</StackPanel>
</Grid>
</Window>
Code behind:
using System;
using System.Data;
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
CreateData();
this.DataContext = Data;
}
public DataSet Data { get; set; }
private void CreateData()
{
Data = new DataSet();
Data.Tables.Add(CreateJobTable());
Data.Tables.Add(CreateSessionsTable());
Data.Tables.Add(CreateBreaks());
DataRelation relation = GetJobSessionRelations();
DataRelation relation2 = GetSessionBreakRelations();
Data.Relations.AddRange(new[] {relation, relation2});
}
private DataTable CreateJobTable()
{
var jobs = new DataTable();
jobs.TableName = "JobDetails";
var col1 = new DataColumn("ID");
var col2 = new DataColumn("Title");
var col3 = new DataColumn("Description");
col1.DataType = Type.GetType("System.Int32");
col2.DataType = Type.GetType("System.String");
col3.DataType = Type.GetType("System.String");
jobs.Columns.Add(col1);
jobs.Columns.Add(col2);
jobs.Columns.Add(col3);
DataRow row = jobs.NewRow();
row["ID"] = 1;
row["Title"] = "Job 1";
row["Description"] = "Job Desc 1";
jobs.Rows.Add(row);
DataRow row2 = jobs.NewRow();
row2["ID"] = 2;
row2["Title"] = "Job 2";
row2["Description"] = "Job Desc 2";
jobs.Rows.Add(row2);
return jobs;
}
private DataTable CreateSessionsTable()
{
var sessions = new DataTable();
sessions.TableName = "SessionDetails";
var col1 = new DataColumn("ID");
var col2 = new DataColumn("Title");
var col3 = new DataColumn("Description");
var col4 = new DataColumn("JobID");
col1.DataType = Type.GetType("System.Int32");
col2.DataType = Type.GetType("System.String");
col3.DataType = Type.GetType("System.String");
col4.DataType = Type.GetType("System.Int32");
sessions.Columns.Add(col1);
sessions.Columns.Add(col2);
sessions.Columns.Add(col3);
sessions.Columns.Add(col4);
DataRow row = sessions.NewRow();
row["ID"] = 1;
row["Title"] = "Session 1";
row["Description"] = "Session Desc 1";
row["JobID"] = 1;
sessions.Rows.Add(row);
DataRow row2 = sessions.NewRow();
row2["ID"] = 2;
row2["Title"] = "Session 2";
row2["Description"] = "Session Desc 2";
row2["JobID"] = 1;
sessions.Rows.Add(row2);
DataRow row3 = sessions.NewRow();
row3["ID"] = 3;
row3["Title"] = "Session 3";
row3["Description"] = "Session Desc 3";
row3["JobID"] = 2;
sessions.Rows.Add(row3);
DataRow row4 = sessions.NewRow();
row4["ID"] = 4;
row4["Title"] = "Session 4";
row4["Description"] = "Session Desc 4";
row4["JobID"] = 2;
sessions.Rows.Add(row4);
return sessions;
}
private DataTable CreateBreaks()
{
var breaks = new DataTable();
breaks.TableName = "BreakDetails";
var col1 = new DataColumn("ID");
var col2 = new DataColumn("Title");
var col3 = new DataColumn("Description");
var col4 = new DataColumn("SessionID");
col1.DataType = Type.GetType("System.Int32");
col2.DataType = Type.GetType("System.String");
col3.DataType = Type.GetType("System.String");
col4.DataType = Type.GetType("System.Int32");
breaks.Columns.Add(col1);
breaks.Columns.Add(col2);
breaks.Columns.Add(col3);
breaks.Columns.Add(col4);
DataRow row = breaks.NewRow();
row["ID"] = 1;
row["Title"] = "Break 1";
row["Description"] = "Break Desc 1";
row["SessionID"] = 1;
breaks.Rows.Add(row);
DataRow row2 = breaks.NewRow();
row2["ID"] = 2;
row2["Title"] = "Break 2";
row2["Description"] = "Break Desc 2";
row2["SessionID"] = 2;
breaks.Rows.Add(row2);
DataRow row3 = breaks.NewRow();
row3["ID"] = 3;
row3["Title"] = "Break 3";
row3["Description"] = "Break Desc 3";
row3["SessionID"] = 3;
breaks.Rows.Add(row3);
DataRow row4 = breaks.NewRow();
row4["ID"] = 4;
row4["Title"] = "Break 4";
row4["Description"] = "Break Desc 4";
row4["SessionID"] = 4;
breaks.Rows.Add(row4);
return breaks;
}
private DataRelation GetSessionBreakRelations()
{
return new DataRelation("relJobDetailsSessionDetails", Data.Tables["JobDetails"].Columns["ID"],
Data.Tables["SessionDetails"].Columns["JobID"]);
}
private DataRelation GetJobSessionRelations()
{
var dataRelation = new DataRelation("relSessionDetailsBreakDetails", Data.Tables["SessionDetails"].Columns["ID"],
Data.Tables["BreakDetails"].Columns["SessionID"]);
return dataRelation;
}
private void lstJobs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void lstSessions_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void lstBreaks_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
}