Domanda

Ho un modello di visualizzazione per gestire un tipo di finestra di dialogo che consente il filtraggio di un elenco (se necessario) e la selezione di un elemento. Il codice funziona bene sia che io abbia impostato IsSynchronizedWithCurrentItem su true o no. La mia comprensione è che questa proprietà non è vera per impostazione predefinita in un ListView, quindi mi piacerebbe capire meglio questa proprietà.

Ecco l'impostazione di associazione in xaml della vista (che funziona altrettanto bene senza l'impostazione della proprietà synch):

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

Il modello di visualizzazione Progetti è in realtà una CollectionViewSource che è supportata da un ObservableCollection privato. Penso di aver preso quest'idea da un progetto di esempio di Josh Smith, ma sinceramente non ricordo proprio ora. Ecco la parte pertinente della VM che si riferisce all'associazione 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 proprietà Filter di CollectionViewSource ha un gestore che restituisce vari predicati sugli elementi del modello di visualizzazione nell'elenco che vengono raccolti correttamente dai binding. Ecco la sintesi di quel codice (che si trova nello stesso 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;
    }

Impostazione della modalità = TwoWay è ridondante poiché l'associazione SelectedItem di ListView è a due vie per impostazione predefinita, ma non mi dispiace essere esplicito al riguardo (potrei sentirmi diversamente su questo una volta che avrò capito meglio WPF).

Che dire del mio codice sta rendendo IsSynchronizedWithCurrentItem = True ridondante?

Il mio istinto è che questo è un codice decente, ma non mi piace che pezzi di esso sembrino funzionare tramite " magic " ;, il che significa che sarei lieto di ricevere feedback costruttivi!

Saluti,
Berryl

È stato utile?

Soluzione

IsSynchronizedWithCurrentItem sincronizza CurrentItem dell'impostazione predefinita CollectionView della collezione associata con SelectedItem del tuo controllo.

Dato che non usi mai il CurrentItem del CollectionView e non sembri legarti alla stessa collezione due volte impostando la proprietà in questione non ha alcun effetto visibile.


Demo di come la proprietà si sincronizza (per i visualizzatori XAML come 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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top