![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
|
Welcome to Vista Forums we are your forum to discuss Windows Vista x64 and x86 systems. Whether you need help or just want to post an idea you have on Vista, this is the forum for you.
br> br> |
| |||||||
![]() |
| | Thread Tools | Display Modes |
| | #1 (permalink) |
| Guest | How to bind to a DataRelation in a DataSet I am trying to display a list of people, and for each person I want to show their corresponding phone numbers. This should be straightforward but it doesn’t work when a Person’s FullName changes. My dataset has two tables, shown below. There is a cascading foreign key DataRelation called FK_Person_Phones. The primary key of each table spans all of its columns. Person (FullName) PersonWithPhone (FullName, Phone) I then create a DataView on the Person table and assign it to the ItemsSource of listBox1. I also assign the underlying DataSet as the DataContext of listBox1. Here’s the relevant Xaml: <ListBox ItemTemplate="{StaticResource personTemplate}" Name="listBox1" /> <DataTemplate x:Key="phoneTemplate"> <StackPanel Orientation="Horizontal" > <TextBox Text="{Binding Path='FullName'}"></TextBox> <TextBox Text="{Binding Path='Phone'}"></TextBox> </StackPanel> </DataTemplate> <DataTemplate x:Key="personTemplate"> <StackPanel Orientation="Vertical"> <TextBox Text="{Binding Path='FullName'}"></TextBox> <ListBox ItemTemplate="{StaticResource phoneTemplate}" ItemsSource="{Binding Path='FK_Person_Phones'}"></ListBox> </StackPanel> </DataTemplate> This all works fine when I pre-populate the dataset. It works when I add people. It works when I add phone numbers for any person that was in the original dataset, or for any person subsequently added - as long as I haven’t changed their original name. BUT – AND HERE IS THE PROBLEM - if I change the name of any person in the Person table the Xaml stops showing their corresponding phone numbers even though the underlying data set reflects the cascading update. I was under the assumption that by binding to the foreign key relation I would always see that parent’s child rows. But it seems as though once the child view is instantiated via the DataRelation the filter on this view is not updated when the parent’s primary key changes – it always tries to show the phone numbers corresponding to the person’s original name. HOW CAN I ALWAYS SHOW EACH PERSON’S CORRESPONDING PHONE NUMBERS EVEN WHEN THEIR NAME CHANGES? |
My System Specs![]() |
| | #2 (permalink) |
| Guest | Re: How to bind to a DataRelation in a DataSet Hi, "jmagaram" <jmagaram@discussions.microsoft.com> wrote in message news:96CD933D-70FE-41C7-A89E-4C9C70FB7233@microsoft.com... >I am trying to display a list of people, and for each person I want to show > their corresponding phone numbers. This should be straightforward but it > doesn't work when a Person's FullName changes. My dataset has two tables, > shown below. There is a cascading foreign key DataRelation called > FK_Person_Phones. The primary key of each table spans all of its columns. > DataView personView = ... ; DataRowView personRowView = personView[0]; DataView childPhonesView = (DataView) personRowView["'FK_Person_Phones"]; The above code illlustrates that the parent DataRowView does have a "column" that returns a child DataView. But you are right there is a problem. The child DataView returned has a fixed set of parent keys, which will not get updated. But that's not the real problem. The real problem is when the parent key changes the parent DataRowView will fire a PropertyChanged but only for the key column, when the key changes the child view should be re-acquired. The child view will only be re-acquired if PropertyChanged would also fire for the the relation-column, but it doesn't. So it's the lack of the right event that causes the problem. Somehow you need to refresh ItemsSource when the name changes, but after having a look this ain't easy, the problem is the DataRowView and hacking into it doesn't seem to be an option. And for some other unknown reason calling UpdateTarget doesn't work even though the parent row at that point returns the correct child DataView. So I ended up with a workaround involving a MultiBinding. MultiBinding allows us to bind to multiple columns. Suppose we bind to name and FK_Person_Phones then the IMultiValueConverter.Convert will be invoked when the name changes, unfortenately FK_Person_Phones is still not refreshed ( lack of event ). So that won't work. But if the MultiBinding would be composed of an empty path Binding and a name Binding, then the converter will be invoked when name changes and we'll have access to the parent DataRowView (because of the empty path binding) and we can pass the FK_Person_Phone through ConverterParameter. Window1.xaml ---------------- .... <Window.Resources> <src:GetChildView x:key="GetChildView" /> <DataTemplate x:Key="phoneTemplate"> <StackPanel Orientation="Horizontal" > <TextBox Text="{Binding Path='FullName'}"></TextBox> <TextBox Text="{Binding Path='Phone'}"></TextBox> </StackPanel> </DataTemplate> <DataTemplate x:Key="personTemplate"> <StackPanel Orientation="Vertical"> <TextBox Text="{Binding Path='FullName'}"></TextBox> <ListBox ItemTemplate="{StaticResource phoneTemplate}" > <ItemsSource> <MultiBinding Converter={StaticResource GetChildView} ConverterParameter = "FK_Person_Phones" > <Binding Path="" /> <Binding Path="FullName"/> </MultiBinding> </ItemsSource> </ListBox> </StackPanel> </DataTemplate> </Window.Resources> .... <!-- set the DataContext to DataView in code behind --> <ListBox Name="listBox1" ItemTemplate="{StaticResource personTemplate}" ItemsSource={Binding} /> .... GetChildView.cs ----------------- public class GetChildView : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return ((DataRowView)values[0])[(string)parameter]; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { throw new Exception("The method or operation is not implemented."); } } HTH, Greetings |
My System Specs![]() |
| | #3 (permalink) |
| Guest | Re: How to bind to a DataRelation in a DataSet Thanks. Very very helpful. "Bart Mermuys" wrote: > Hi, > > "jmagaram" <jmagaram@discussions.microsoft.com> wrote in message > news:96CD933D-70FE-41C7-A89E-4C9C70FB7233@microsoft.com... > >I am trying to display a list of people, and for each person I want to show > > their corresponding phone numbers. This should be straightforward but it > > doesn't work when a Person's FullName changes. My dataset has two tables, > > shown below. There is a cascading foreign key DataRelation called > > FK_Person_Phones. The primary key of each table spans all of its columns. > > > > DataView personView = ... ; > DataRowView personRowView = personView[0]; > > DataView childPhonesView = (DataView) personRowView["'FK_Person_Phones"]; > > The above code illlustrates that the parent DataRowView does have a "column" > that returns a child DataView. But you are right there is a problem. The > child DataView returned has a fixed set of parent keys, which will not get > updated. But that's not the real problem. > > The real problem is when the parent key changes the parent DataRowView will > fire a PropertyChanged but only for the key column, when the key changes the > child view should be re-acquired. The child view will only be re-acquired > if PropertyChanged would also fire for the the relation-column, but it > doesn't. > > So it's the lack of the right event that causes the problem. Somehow you > need to refresh ItemsSource when the name changes, but after having a look > this ain't easy, the problem is the DataRowView and hacking into it doesn't > seem to be an option. And for some other unknown reason calling > UpdateTarget doesn't work even though the parent row at that point returns > the correct child DataView. > > So I ended up with a workaround involving a MultiBinding. MultiBinding > allows us to bind to multiple columns. Suppose we bind to name and > FK_Person_Phones then the IMultiValueConverter.Convert will be invoked when > the name changes, unfortenately FK_Person_Phones is still not refreshed ( > lack of event ). So that won't work. But if the MultiBinding would be > composed of an empty path Binding and a name Binding, then the converter > will be invoked when name changes and we'll have access to the parent > DataRowView (because of the empty path binding) and we can pass the > FK_Person_Phone through ConverterParameter. > > > Window1.xaml > ---------------- > .... > <Window.Resources> > <src:GetChildView x:key="GetChildView" /> > > <DataTemplate x:Key="phoneTemplate"> > <StackPanel Orientation="Horizontal" > > <TextBox Text="{Binding Path='FullName'}"></TextBox> > <TextBox Text="{Binding Path='Phone'}"></TextBox> > </StackPanel> > </DataTemplate> > > <DataTemplate x:Key="personTemplate"> > <StackPanel Orientation="Vertical"> > <TextBox Text="{Binding Path='FullName'}"></TextBox> > <ListBox ItemTemplate="{StaticResource phoneTemplate}" > > <ItemsSource> > <MultiBinding Converter={StaticResource GetChildView} > ConverterParameter = "FK_Person_Phones" > > <Binding Path="" /> > <Binding Path="FullName"/> > </MultiBinding> > </ItemsSource> > </ListBox> > </StackPanel> > </DataTemplate> > </Window.Resources> > .... > > <!-- set the DataContext to DataView in code behind --> > <ListBox Name="listBox1" > ItemTemplate="{StaticResource personTemplate}" > ItemsSource={Binding} /> > .... > > GetChildView.cs > ----------------- > public class GetChildView : IMultiValueConverter > { > public object Convert(object[] values, Type targetType, object parameter, > System.Globalization.CultureInfo culture) > { > return ((DataRowView)values[0])[(string)parameter]; > } > > public object[] ConvertBack(object value, Type[] targetTypes, object > parameter, System.Globalization.CultureInfo culture) > { > throw new Exception("The method or operation is not implemented."); > } > } > > > HTH, > Greetings > > > > > |
My System Specs![]() |
| | #4 (permalink) |
| Guest | Re: How to bind to a DataRelation in a DataSet Thanks. Very very helpful. "Bart Mermuys" wrote: > Hi, > > "jmagaram" <jmagaram@discussions.microsoft.com> wrote in message > news:96CD933D-70FE-41C7-A89E-4C9C70FB7233@microsoft.com... > >I am trying to display a list of people, and for each person I want to show > > their corresponding phone numbers. This should be straightforward but it > > doesn't work when a Person's FullName changes. My dataset has two tables, > > shown below. There is a cascading foreign key DataRelation called > > FK_Person_Phones. The primary key of each table spans all of its columns. > > > > DataView personView = ... ; > DataRowView personRowView = personView[0]; > > DataView childPhonesView = (DataView) personRowView["'FK_Person_Phones"]; > > The above code illlustrates that the parent DataRowView does have a "column" > that returns a child DataView. But you are right there is a problem. The > child DataView returned has a fixed set of parent keys, which will not get > updated. But that's not the real problem. > > The real problem is when the parent key changes the parent DataRowView will > fire a PropertyChanged but only for the key column, when the key changes the > child view should be re-acquired. The child view will only be re-acquired > if PropertyChanged would also fire for the the relation-column, but it > doesn't. > > So it's the lack of the right event that causes the problem. Somehow you > need to refresh ItemsSource when the name changes, but after having a look > this ain't easy, the problem is the DataRowView and hacking into it doesn't > seem to be an option. And for some other unknown reason calling > UpdateTarget doesn't work even though the parent row at that point returns > the correct child DataView. > > So I ended up with a workaround involving a MultiBinding. MultiBinding > allows us to bind to multiple columns. Suppose we bind to name and > FK_Person_Phones then the IMultiValueConverter.Convert will be invoked when > the name changes, unfortenately FK_Person_Phones is still not refreshed ( > lack of event ). So that won't work. But if the MultiBinding would be > composed of an empty path Binding and a name Binding, then the converter > will be invoked when name changes and we'll have access to the parent > DataRowView (because of the empty path binding) and we can pass the > FK_Person_Phone through ConverterParameter. > > > Window1.xaml > ---------------- > .... > <Window.Resources> > <src:GetChildView x:key="GetChildView" /> > > <DataTemplate x:Key="phoneTemplate"> > <StackPanel Orientation="Horizontal" > > <TextBox Text="{Binding Path='FullName'}"></TextBox> > <TextBox Text="{Binding Path='Phone'}"></TextBox> > </StackPanel> > </DataTemplate> > > <DataTemplate x:Key="personTemplate"> > <StackPanel Orientation="Vertical"> > <TextBox Text="{Binding Path='FullName'}"></TextBox> > <ListBox ItemTemplate="{StaticResource phoneTemplate}" > > <ItemsSource> > <MultiBinding Converter={StaticResource GetChildView} > ConverterParameter = "FK_Person_Phones" > > <Binding Path="" /> > <Binding Path="FullName"/> > </MultiBinding> > </ItemsSource> > </ListBox> > </StackPanel> > </DataTemplate> > </Window.Resources> > .... > > <!-- set the DataContext to DataView in code behind --> > <ListBox Name="listBox1" > ItemTemplate="{StaticResource personTemplate}" > ItemsSource={Binding} /> > .... > > GetChildView.cs > ----------------- > public class GetChildView : IMultiValueConverter > { > public object Convert(object[] values, Type targetType, object parameter, > System.Globalization.CultureInfo culture) > { > return ((DataRowView)values[0])[(string)parameter]; > } > > public object[] ConvertBack(object value, Type[] targetTypes, object > parameter, System.Globalization.CultureInfo culture) > { > throw new Exception("The method or operation is not implemented."); > } > } > > > HTH, > Greetings > > > > > |
My System Specs![]() |
![]() |
| Thread Tools | |
| Display Modes | |
| |
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| How to bind to AD without displaying the Distinguished Name | John | PowerShell | 11 | 04-18-2008 09:02 AM |
| Winforms User Controls - How do I bind those to a dataset on the host form | John Sheppard | .NET General | 0 | 04-14-2008 09:49 PM |
| in a bind | tony | Vista mail | 1 | 09-07-2007 09:07 PM |
| Bind to LDAP Directory | Tom G. | PowerShell | 11 | 12-27-2006 12:59 PM |
| UserControl cannot bind to its own properties? | lubomir@gmail.com | Avalon | 3 | 01-31-2006 06:59 AM |