Атрибут IsSynchronizedWithCurrentItem и текущие обновления элемента - PullRequest
10 голосов
/ 01 декабря 2009

У меня есть модель представления для управления типом диалога, который позволяет фильтровать список (при необходимости) и выбирать элемент. Код работает нормально, независимо от того, установил ли я IsSynchronizedWithCurrentItem в true или нет. Насколько я понимаю, это свойство не является истинным по умолчанию в ListView, поэтому я хотел бы лучше понять это свойство.

Вот настройка привязки в представлении xaml (которое работает так же хорошо без установки свойства синхронизации):

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

Модель представления Projects на самом деле представляет собой CollectionViewSource, который поддерживается частной ObservableCollection. Я думаю, что я воплотил эту идею в пример проекта Джоша Смита, но, честно говоря, сейчас не вспоминаю. Вот соответствующая часть виртуальной машины, которая относится к привязке 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; }

Свойство Filter в CollectionViewSource имеет обработчик, который возвращает различные предикаты для элементов модели представления в списке, которые правильно подобраны привязками. Вот суть этого кода (который находится в том же 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;
    }

Установка режима = TwoWay является избыточным, поскольку привязка SeViewItem в ListView по умолчанию является двухсторонней, но я не возражаю быть откровенным по этому поводу (я могу почувствовать себя по-другому, когда лучше пойму WPF).

Что в моем коде делает IsSynchronizedWithCurrentItem = True избыточным?

Меня интересует, что это приличный код, но мне не нравится, что его части, кажется, работают через "магию", а это значит, что я приветствую любые конструктивные отзывы!

Приветствия
Berryl

1 Ответ

18 голосов
/ 14 июня 2011

IsSynchronizedWithCurrentItem синхронизирует CurrentItem по умолчанию CollectionView связанной коллекции с SelectedItem вашего элемента управления.

Поскольку вы никогда не используете CurrentItem из CollectionView, и вы не связываетесь с одной и той же коллекцией дважды, установка рассматриваемого свойства вообще не имеет видимого эффекта.


Демонстрация того, как свойство синхронизируется (для средств просмотра XAML, таких как Kaxaml или 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>
...