How do I change the binding of a CollectionView.Source?
Initially I had this code in XAML:
<CollectionViewSource x:Name="cSource">
<CollectionViewSource.Source>
<Binding Source="{StaticResource NameOfXmlDataProvider}" XPath="letter"/>
</CollectionViewSource.Source>
<CollectionViewSource>
But I wanted to keep a binding object in the C# code, to be able to dynamically alter it's xpath. Currently I have this code:
CollectionViewSource viewSource = this.FindResource("cSource") as CollectionViewSource;
Binding binding = new Binding( "Source" );
binding.Source = _xmlDataProvider;
binding.XPath = "/new/path/to/nodes";
BindingOperations.SetBinding( viewSource, CollectionViewSource.SourceProperty, binding );
This compiles and doesn't complain but when called it only leads to an empty list. I can't seem to find related examples in the web - most of them deal with the data provid开发者_JAVA百科ers but I want to change the binding.
- Anybody knows how to fix this?
- Or is there a better way to do this?
- Maybe from retrieving the binding object from the collectionview and changing it?
Rather than bind to a static resource in the XAML (yuk) or dynamically change the binding (yukkier), bind to things you can change.
<CollectionViewSource x:Name="cSource">
<CollectionViewSource.Source>
<Binding Source="{Binding MyDataProviderProperty}" XPath="{Binding MyDataXPathProperty}"/>
</CollectionViewSource.Source>
<CollectionViewSource>
If you don't want to go full MVVM, a nice trick is that you can bind your page DataContext to your page's code-behind class by simply naming the UserControl
element of your page and use ElementName
to bind the datacontext to it (the only restriction is that the DataContext binding can't also be on the UserControl (so place it on the first child, like a grid):
<UserControl x:Class="BindingTests.BindingToSelfExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" x:Name="MyViewClass">
<Grid x:Name="LayoutRoot" Background="White" DataContext="{Binding ElementName=MyViewClass}">
<TextBlock Text="{Binding SomePropertyOfTheCodeBehind}" Width="100" Height="20"/>
</Grid>
</UserControl>
Now, so long as you have notify properties on your code behind called MyDataProviderProperty and MyDataXPath, you can change them to your heart's content.
You need to use the SetBinding()
Method of collView. Should be something like collView.SetBinding(CollectionViewSource.SourceProperty, binding)
Look at http://msdn.microsoft.com/en-us/library/ms752347.aspx for further reference.
The problem with the code from the question is the Source
in the binding. So what works is:
Binding binding = new Binding();
If the Constructor is used with a parameter, the parameter is set as the Path
of the binding. The (additional) XPath
of the binding is then used from that path. So it tried to find "Source" in the XML which lead to an empty selection. The xpath was then working on an empty set of nodes.
So it is possible to use the bindings from the code.
Try this:
ICollectionView cSource {get;set;}
In the constructor:
cSource = new CollectionViewSource{Source = "myDataSource"}.View;
Then when you need to change the collection view source:
cSource = new CollectionViewSource{Source = "newDataSource"}.View;
Then if for instance it is a datagrid, you would call:
DG.ItemsSource = cSource;
DG.Items.Refresh();
Datagrid will now be showing the updated source data.
精彩评论