How do I change the binding of a CollectionView.So

2019-07-25 17:02发布

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 providers 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?

4条回答
我命由我不由天
2楼-- · 2019-07-25 17:20

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.

查看更多
Root(大扎)
3楼-- · 2019-07-25 17:24

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.

查看更多
Rolldiameter
4楼-- · 2019-07-25 17:29

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.

查看更多
Summer. ? 凉城
5楼-- · 2019-07-25 17:39

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.

查看更多
登录 后发表回答