Pregunta

Tengo un modelo de vista para administrar un tipo de vista de diálogo que permite filtrar una lista (si es necesario) y seleccionar un elemento. El código funciona bien si configuro IsSynchronizedWithCurrentItem en verdadero o no. Tengo entendido que esta propiedad no es verdadera por defecto en un ListView, por lo que me gustaría entender mejor esta propiedad.

Aquí está la configuración de enlace en la vista xaml (que funciona igual de bien sin la configuración de la propiedad de sincronización):

    <ListView  
          ItemsSource="{Binding Projects.View}" 
          IsSynchronizedWithCurrentItem="True"
          SelectedItem="{Binding SelectedProject, Mode=TwoWay}"             
                      >

El modelo de vista Proyectos es en realidad un CollectionViewSource respaldado por una ObservableCollection privada. Creo que saqué esta idea de un proyecto de muestra de Josh Smith, pero honestamente no recuerdo en este momento. Aquí está la parte relevante de la VM que se relaciona con el enlace xaml:

private ObservableCollection<ProjectViewModel> _projectsInternal { get; set; }
public CollectionViewSource Projects { get; set; }

private void _populateProjectListings(IEnumerable<Project> openProjects) {
    var listing = (from p in openProjects 
                   orderby p.Code.ToString()
                   select new ProjectViewModel(p)).ToList();

    foreach (var pvm in listing)
            pvm.PropertyChanged += _onProjectViewModelPropertyChanged;

    _projectsInternal = new ObservableCollection<ProjectViewModel>(listing);

    Projects = new CollectionViewSource {Source = _projectsInternal};
}

/// <summary>Property that is updated via the binding to the view</summary>
public ProjectViewModel SelectedProject { get; set; }

La propiedad Filter de CollectionViewSource tiene un controlador que devuelve varios predicados en los elementos del modelo de vista en la lista que los enlaces recogen correctamente. Aquí está la esencia de ese código (que está en el mismo ProjectSelctionViewModel):

    /// <summary>Trigger filtering of the <see cref="Projects"/> listing.</summary>
    public void Filter(bool applyFilter)
    {
        if (applyFilter)
            Projects.Filter += _onFilter;
        else
            Projects.Filter -= _onFilter;

        OnPropertyChanged<ProjectSelectionViewModel>(vm=>vm.Status);
    }

    private void _onFilter(object sender, FilterEventArgs e)
    {
        var project = e.Item as ProjectViewModel;
        if (project == null) return;

        if (!project.IsMatch_Description(DescriptionText)) e.Accepted = false;
        if (!project.IsMatch_SequenceNumber(SequenceNumberText)) e.Accepted = false;
        if (!project.IsMatch_Prefix(PrefixText)) e.Accepted = false;
        if (!project.IsMatch_Midfix(MidfixText)) e.Accepted = false;
        if (!project.IsAvailable) e.Accepted = false;
    }

Establecer el Modo = TwoWay es redundante ya que el enlace SelectedItem de ListView es bidireccional de manera predeterminada, pero no me importa ser explícito al respecto (podría sentirme diferente al respecto una vez que comprenda mejor WPF).

¿Qué pasa con mi código que hace que IsSynchronizedWithCurrentItem = True sea redundante?

Mi instinto es que este es un código decente, pero no me gusta que sus partes parezcan funcionar a través de "magic", lo que significa que agradecería cualquier comentario constructivo.

Saludos,
Berryl

¿Fue útil?

Solución

IsSynchronizedWithCurrentItem sincroniza el CurrentItem del predeterminado CollectionView de la colección enlazada con el SelectedItem de su control.

Dado que nunca utiliza el CurrentItem del CollectionView y no parece vincularse a la misma colección dos veces, configurar la propiedad en cuestión no tiene ningún efecto visible.


Demostración de cómo se sincroniza la propiedad (para espectadores XAML como Kaxaml o XAMLPad):

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <x:Array x:Key="Items" Type="{x:Type sys:String}">
            <sys:String>Apple</sys:String>
            <sys:String>Orange</sys:String>
            <sys:String>Pear</sys:String>
            <sys:String>Lime</sys:String>
        </x:Array>
    </Page.Resources>
    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <StackPanel Background="Transparent">
            <ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{StaticResource Items}" />
            <ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{StaticResource Items}" />
            <!-- This TextBlock binds to the CurrentItem of the Items via the "/" -->
            <TextBlock Text="{Binding Source={StaticResource Items}, Path=/}"/>
        </StackPanel>
    </ScrollViewer>
</Page>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top