Pregunta

Tengo un archivo 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}}" />

y su clase de código subyacente, donde he definido el filtro para el detalle 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;
            }
        }
    }
}

A continuación, hay la clase 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;
}

Por último, una enumeración:

public enum DetailScope
{
  Private, 
  Business, 
  Other
}

Cuando ejecuto mi código, aparece un cuadro de lista poblada con un montón de detalles de la cuenta, cada uno con su propio cuadro combinado con un alcance seleccionado y un cuadro de texto con el valor apropiado. El problema es que todos los valores seleccionados en los cuadros combinados coinciden con el juego alcance para el último detalle entrado y cambiar cualquiera de los valores de cuadro combinado actualiza todos ellos, como si todos ellos están ligados al mismo detalle cuenta.

Cuando saco la ObjectDataProvider de los DetailScopes CollectionViewSource y se unen directamente a ItemsSource del cuadro combinado en el DataTemplate AccountDetail, el problema se ha ido. Sin embargo, lo hago dentro de la CollectionViewSource necesidad porque yo estoy aplicando algún tipo de filtrado a la misma y que no podría aplicar el filtrado a ObjectDataProvider.

Podría alguien explicar por qué sucede esto y cómo soy yo en realidad supone que CollectionViewSource conexión y ObjectDataProvider? Gracias.

¿Fue útil?

Solución

.

El problema con el código es que cada ComboBox está utilizando la misma instancia de CollectionViewSource ; Eso significa que, con el recurso "DetailScopes" clave es compartida por todos ComboBox, por lo que cada vez que seleccione un valor de un cuadro combinado particular, se selecciona automáticamente el mismo valor en todos los ComboBox. Es porque la colección subyacente que se comparte, no pierde de vista el elemento seleccionado, y ya que cambia sobre la selección de un cuadro combinado, los notifica CollectionViewSource el cambio a todos ComboBox .

Así que la solución es muy simple. Todo lo necesario para hacer de recursos DetailScopes no compartible .

Aquí está la solución:

<!-- 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>

La esperanza que resuelve su problema!

Sin embargo, esta solución va a causar otro problema. Permítanme citar algo de MSDN, por lo que vas a entender lo que x:. Hace Compartida

  

x: Shared Atributo

     

Cuando se establece en falso, modifica Wpf de recursos de recuperación   comportamiento para que las solicitudes de   recursos atribuidos crear una nueva   instancia para cada solicitud en lugar de   compartir la misma instancia para todos   peticiones.

Como x: Compartido hace para crear una nueva instancia (una nueva copia) del recurso cada vez que intenten acceder a ella, eso quiere decir, el método de controlador de filtro está unido sólo a la instancia que se obtiene en el código subyacente, no todas las instancias.

Así que con el fin de trabajar el controlador correctamente, es necesario adjuntar el controlador de sí mismo XAML, como esto:

<!-- 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>

La esperanza que resuelve todos sus problemas. Déjame saber si todavía se enfrentan a ningún: -).

Ah, por cierto, el siguiente código subyacente no se necesita más. Así que por favor eliminarlo.

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

.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top