atributo IsSynchronizedWithCurrentItem e atualizações item atual
-
10-07-2019 - |
Pergunta
Eu tenho um modelo vista para gerir um tipo de diálogo de vista que permite a filtragem de uma lista (se necessário) e seleção de um item. O código funciona bem se eu definir IsSynchronizedWithCurrentItem a verdade ou não. O meu entendimento é que esta propriedade não é verdadeiro por padrão em um ListView, então eu gostaria de entender melhor essa propriedade.
Aqui está a configuração de ligação em XAML da vista (que funciona tão bem sem a definição de propriedade sincronia):
<ListView
ItemsSource="{Binding Projects.View}"
IsSynchronizedWithCurrentItem="True"
SelectedItem="{Binding SelectedProject, Mode=TwoWay}"
>
a vista do modelo Projetos é realmente um CollectionViewSource que é apoiado por uma ObservableCollection privado. Acho que glommed esta ideia de um projeto de exemplo de Josh Smith, mas eu sinceramente não me lembro agora. Aqui está a parte relevante da VM que se relaciona com o XAML ligação:
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; }
A propriedade de filtro do CollectionViewSource tem um manipulador que retorna vários predicados sobre os itens vista modelo na lista que é captado pelas ligações corretamente. Aqui está a essência do que o código (que está na mesma 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;
}
Definir o modo = TwoWay é redundante, dado obrigatório SelectedItem do ListView é bidirecional por padrão, mas eu não me importo de ser explícito sobre isso (eu poderia sentir de maneira diferente sobre isso uma vez eu entendo WPF melhor).
E o meu código está fazendo o IsSynchronizedWithCurrentItem = True redundante?
Meu instinto é que este é o código decente, mas eu não gosto disso pedaços dela parecem estar a trabalhar através de "mágica", que significa que eu gostaria de receber qualquer feedback construtivo!
Cheers,
Berryl
Solução
sincroniza IsSynchronizedWithCurrentItem
CurrentItem
do default CollectionView
da coleção ligada com o SelectedItem
do seu controle.
Uma vez que você nunca usa o CurrentItem
do CollectionView
e você não parece ligar-se à mesma coleção definindo duas vezes a propriedade em questão não tem nenhum efeito visível.
Demonstração de como as sincroniza propriedade (para os telespectadores XAML como Kaxaml ou 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>