Question

J'ai un fichier MainWindow.xaml:

<Window.Resources>

  <CollectionViewSource x:Key="cvs" 
    Source="{Binding Source={StaticResource ResourceKey=DetailsCollection}}" />

  <CollectionViewSource x:Key="DetailScopes">
    <CollectionViewSource.Source>
      <ObjectDataProvider 
        MethodName="GetValues" 
        ObjectType="{x:Type system:Enum}">
        <ObjectDataProvider.MethodParameters>
          <x:Type TypeName="entities:DetailScope" />
        </ObjectDataProvider.MethodParameters>
      </ObjectDataProvider>
    </CollectionViewSource.Source>
  </CollectionViewSource>

  <DataTemplate x:Key="AccountDetail"
    DataType="{x:Type entities:AccountDetail}">
    <DockPanel>
      <ComboBox 
        DockPanel.Dock="Left" 
        ItemsSource="{Binding Source={StaticResource ResourceKey=DetailScopes}}" 
        SelectedItem="{Binding Path=Scope}">
        <ComboBox.ItemTemplate>
          <DataTemplate>
            <TextBlock 
              Text="{Binding Converter={StaticResource DetailScopeConverter}}" />
          </DataTemplate>
        </ComboBox.ItemTemplate>
      </ComboBox>
      <TextBox Text="{Binding Path=Value}" />
    </DockPanel>
  </DataTemplate>

</Window.Resources>

...

<ListBox 
  ItemTemplate="{StaticResource ResourceKey=AccountDetail}" 
  ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}" />

et son code-behind classe, où je définissais le filtre pour les détails Scopes:

public class MainWindow
{
    public MainWindow()
    {
        CollectionViewSource detailScopes;

        InitializeComponent();

        // Attach filter to the collection view source
        detailScopes = this.Resources["DetailScopes"] as CollectionViewSource;
        detailScopes.Filter += new FilterEventHandler(DetailScopesFilter);

        private void DetailScopesFilter(object sender, FilterEventArgs e)
        {
            DetailScope scope;

            scope = (DetailScope)e.Item;
            if (scope == DetailScope.Private ||
                scope == DetailScope.Business)
            {
                e.Accepted = true;
            }
            else
            {
                e.Accepted = false;
            }
        }
    }
}

Ensuite, il y a la classe AccountDetail:

public class AccountDetail
{
  public string Value
  {
    get { return this.value; }
    set { this.value = value; }
  }
  public DetailScope Scope
  {
    get { return scope; }
    set { scope = value; }
  }

  private string value;
  private DetailScope scope;
}

Enfin, un ENUM:

public enum DetailScope
{
  Private, 
  Business, 
  Other
}

Quand je lance mon code, je reçois une zone de liste peuplée avec un tas de détails de compte, chacun ayant sa propre zone de liste déroulante avec une portée sélectionnée et une zone de texte avec la valeur appropriée. Le problème est que toutes les valeurs sélectionnées dans les zones de liste déroulante correspondent à l'ensemble de la portée du dernier détail entré et en changeant toutes les valeurs de la boîte combo met à jour tous, comme ils sont tous liés au même détail compte.

Quand je prends le ObjectDataProvider des DetailScopes de CollectionViewSource et se lient directement à la ItemsSource de zone de liste déroulante dans le DataTemplate AccountDetail, le problème a disparu. Cependant, je besoin à l'intérieur du CollectionViewSource parce que je pose ma candidature à un certain filtrage et je ne peux pas appliquer le filtrage à ObjectDataProvider.

Quelqu'un pourrait-il expliquer pourquoi s'il vous plaît est ce qui se passe et comment suis-je censé réellement connecter CollectionViewSource et ObjectDataProvider? Merci.

Était-ce utile?

La solution

.

Le problème avec votre code est que chaque ComboBox utilise la même instance de CollectionViewSource ; cela veut dire, la ressource avec la touche « DetailScopes » est partagée par tous ComboBox, donc chaque fois que vous sélectionnez une valeur à partir d'une zone de liste déroulante particulier, il sélectionne automatiquement la même valeur dans tous ComboBox. C'est parce que la collection sous-jacente qui est partagée, garde la trace de l'élément sélectionné, et puisqu'il change sur la sélection d'une zone de liste déroulante, les CollectionViewSource notifie le changement à tous ComboBox .

Donc, la solution est très simple. Tout ce que vous devez faire des ressources DetailScopes impartageable .

Voici le correctif:

<!-- Please note this x:Shared="False" just after x:Key="DetailsScopes" --->

<CollectionViewSource x:Key="DetailScopes"  x:Shared="False"> 
    <CollectionViewSource.Source>
      <ObjectDataProvider 
        MethodName="GetValues" 
        ObjectType="{x:Type system:Enum}">
        <ObjectDataProvider.MethodParameters>
          <x:Type TypeName="entities:DetailScope" />
        </ObjectDataProvider.MethodParameters>
      </ObjectDataProvider>
    </CollectionViewSource.Source>
  </CollectionViewSource>

Hope il résout votre problème!

Cependant, cette solution entraînera un autre problème. Permettez-moi de citer quelque chose de MSDN, de sorte que vous comprendrez ce que x. Fait partagé

  

x: Shared Attribute

     

Lorsque la valeur false, modifie WPF-récupération des ressources   comportement afin que les demandes de   ressource attribuée créer une nouvelle   par exemple pour chaque demande au lieu   partageant la même instance pour tous   demandes.

Depuis x: Partagé fait pour créer une nouvelle instance (une nouvelle copie) de la ressource chaque fois que vous tentez d'y accéder, ce moyen, la méthode de gestionnaire de filtre est attaché uniquement à l'instance que vous obtenez dans le code-behind, pas tous les cas.

Ainsi, afin de travailler votre gestionnaire correctement, vous devez joindre le gestionnaire de XAML lui-même, comme ceci:

<!-- Now please note Filter="DetailsScopesFilter" --->

<CollectionViewSource x:Key="DetailScopes"  x:Shared="False"  Filter="DetailScopesFilter"> 
    <CollectionViewSource.Source>
      <ObjectDataProvider 
        MethodName="GetValues" 
        ObjectType="{x:Type system:Enum}">
        <ObjectDataProvider.MethodParameters>
          <x:Type TypeName="entities:DetailScope" />
        </ObjectDataProvider.MethodParameters>
      </ObjectDataProvider>
    </CollectionViewSource.Source>
  </CollectionViewSource>

Hope il résout tous vos problèmes. Faites-moi savoir si vous faites face à encore un: -.)

Oh en passant, ce qui suit code-behind est plus nécessaire. Alors, s'il vous plaît le supprimer.

    // Attach filter to the collection view source
    detailScopes = this.Resources["DetailScopes"] as CollectionViewSource;
    detailScopes.Filter += new FilterEventHandler(DetailScopesFilter);

.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top