.NET Framework Developer Center >
.NET Development Forums
>
Windows Presentation Foundation (WPF)
>
Binding to XML through ComboBox
Binding to XML through ComboBox
- VS2008 source here
I have a master-detail scenario in which I am attempting to bind to an XAttribute's value with a ComboBox. I have an enum that I want to filter a value from, and I've done so with a CollectionViewSource with a filter method. Simple enough. I then bind that CVS as my ItemsSource on a ComboBox and bind the selectedvalue of the combo to the templated item's Value attribute. This all works with no problems.
Problems begin to arise when you do the following: open the root of the TreeView. Click the ChildElement. The ComboBox fills as expected. Change the value in the ComboBox and the XML updates as expected. Click on the root again. Click back on the ChildElement. In the output window there is a Data error saying "cannot save value from target back to source" and the ComboBox is blank.
If I bind the combo box's ItemsSource instead to the ObjectDataProvider directly, forgoing the CVS, it works fine. I've removed the filter function from the CVS as well and it still gives the error and wipes the combo box. Am I doing something wrong here?
Thanks!
- Edited byDashus Friday, June 06, 2008 1:21 PMMalformed code link
Answers
- I've said that this is an intentional feature, when you use CollectionViewSource, WPF assumes that you are mostly likely to use it for master/detail binding scenario which needs to drive the setting of current item, so here is too XAMLPad ready example:
The one use the implicit collection view:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Page.Resources>
<x:Array Type="{x:Type sys:String}" x:Key="data">
<sys:String>Paviel Dedved</sys:String>
<sys:String>Andriy Shevchenko</sys:String>
<sys:String>Paolo Maldini</sys:String>
<sys:String>Robert Baggio</sys:String>
<sys:String>Alessandro Del Piero</sys:String>
</x:Array>
</Page.Resources>
<StackPanel>
<ListBox
Width="200"
Height="200"
BorderBrush="Navy"
BorderThickness="1"
ItemsSource="{Binding Source={StaticResource data}}"/>
<ListBox
Width="200"
Height="200"
BorderBrush="Navy"
BorderThickness="1"
ItemsSource="{Binding Source={StaticResource data}}"/>
</StackPanel>
</Page>
You will find that two ListBox can independently select their item without currency synchronization, but if you use CollectionViewSource as follows:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Page.Resources>
<x:Array Type="{x:Type sys:String}" x:Key="data">
<sys:String>Paviel Dedved</sys:String>
<sys:String>Andriy Shevchenko</sys:String>
<sys:String>Paolo Maldini</sys:String>
<sys:String>Robert Baggio</sys:String>
<sys:String>Alessandro Del Piero</sys:String>
</x:Array>
<CollectionViewSource x:Key="src" Source="{StaticResource data}"/>
</Page.Resources>
<StackPanel>
<ListBox
Width="200"
Height="200"
BorderBrush="Navy"
BorderThickness="1"
ItemsSource="{Binding Source={StaticResource src}}"/>
<ListBox
Width="200"
Height="200"
BorderBrush="Navy"
BorderThickness="1"
ItemsSource="{Binding Source={StaticResource src}}"/>
</StackPanel>
</Page>
You will find that WPF is trying to synchronize the selection with the current item be default, which is mostly likely to be the result developers expects:)
Hope this makes sense to you.
- Marked As Answer byMarco Zhou Thursday, June 12, 2008 10:43 AM
All Replies
- It seems that WPF makes a difference between implicit CollectionView and explicit CollectionView, to workaround this issue, you could directly bind the ObjectDataProvider to the ComboBox control, bypassing the explicit CollectionView generated by CollectionViewSource entirely as follows:
<ComboBox
ItemsSource="{Binding Source={StaticResource FullEnumDataSource}}"
SelectedValue="{Binding Path=Attribute[Value].Value}"
Loaded="ComboBox_Loaded"/>
To sort and filter the implicit CollectionView generated by WPF's binding engine, you could hook up to ComboBox's Loaded event, and in the loaded event handler, you could write something like the following:
private void ComboBox_Loaded(object sender, RoutedEventArgs e)
{
ComboBox comboBox = (ComboBox)sender;
comboBox.Items.Filter += (item) =>
{
return (item as string) != "EnumValueFour";
};
}
Hope this helps
- Well this works for the sample app but I had to make a slight change to my actual app:
Instead of GetNames I had to use GetValues and provide a converter on the SelectedValue for the ComboBox.
Out of curiousity, is this a bug? It seems like what I'm trying to do should work regardless of the explicit/implicit-ness of the CollectionView.
- I've said that this is an intentional feature, when you use CollectionViewSource, WPF assumes that you are mostly likely to use it for master/detail binding scenario which needs to drive the setting of current item, so here is too XAMLPad ready example:
The one use the implicit collection view:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Page.Resources>
<x:Array Type="{x:Type sys:String}" x:Key="data">
<sys:String>Paviel Dedved</sys:String>
<sys:String>Andriy Shevchenko</sys:String>
<sys:String>Paolo Maldini</sys:String>
<sys:String>Robert Baggio</sys:String>
<sys:String>Alessandro Del Piero</sys:String>
</x:Array>
</Page.Resources>
<StackPanel>
<ListBox
Width="200"
Height="200"
BorderBrush="Navy"
BorderThickness="1"
ItemsSource="{Binding Source={StaticResource data}}"/>
<ListBox
Width="200"
Height="200"
BorderBrush="Navy"
BorderThickness="1"
ItemsSource="{Binding Source={StaticResource data}}"/>
</StackPanel>
</Page>
You will find that two ListBox can independently select their item without currency synchronization, but if you use CollectionViewSource as follows:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Page.Resources>
<x:Array Type="{x:Type sys:String}" x:Key="data">
<sys:String>Paviel Dedved</sys:String>
<sys:String>Andriy Shevchenko</sys:String>
<sys:String>Paolo Maldini</sys:String>
<sys:String>Robert Baggio</sys:String>
<sys:String>Alessandro Del Piero</sys:String>
</x:Array>
<CollectionViewSource x:Key="src" Source="{StaticResource data}"/>
</Page.Resources>
<StackPanel>
<ListBox
Width="200"
Height="200"
BorderBrush="Navy"
BorderThickness="1"
ItemsSource="{Binding Source={StaticResource src}}"/>
<ListBox
Width="200"
Height="200"
BorderBrush="Navy"
BorderThickness="1"
ItemsSource="{Binding Source={StaticResource src}}"/>
</StackPanel>
</Page>
You will find that WPF is trying to synchronize the selection with the current item be default, which is mostly likely to be the result developers expects:)
Hope this makes sense to you.
- Marked As Answer byMarco Zhou Thursday, June 12, 2008 10:43 AM
- What if we're using a TextBox? The problem I am getting right now is in this scenario:
I have a XamDataGrid (infragistics control) and some TextBoxes to apply filters on the XamDataGrid, as follows:
<UserControl.Resources> <ObjectDataProvider x:Name="pvd" ObjectType="{x:Type <WCF Service Contract>}" MethodName="<WCF operation contract>"> <ObjectDataProvider.MethodParameters> <x:Static Member="system:DateTime.Now"/> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </UserControl.Resources> ... <TextBox Name="txtDate" Text="{Binding Source={StaticResource pvd}, Path="MethodParameters[0]", UpdateSourceTrigger="LostFocus", BindsDirectlyToSource="True", Mode="TwoWay", Convert="{StaticResource StringToDate}"/> ... <igDP:XamDataGrid Name="xdgData" DataSource="{Binding Source={StaticResource pvd}}"/>
Looks like the constant binding in each element is making WPF to crash... but I am not certain...
The error I got is:
System.Windows.Data Error: 8 : Cannot save value from target back to source. BindingExpression:Path=MethodParameters[0]; DataItem='ObjectDataProvider' (HashCode=43631048); target element is 'TextBox' (Name='txtDate'); target property is 'Text' (type 'String') TargetInvocationException:'System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at Infragistics.Windows.DataPresenter.RecordManager.d.a()
Any Ideas?


