wpf IsSynchronizedWithCurrentItem 属性和当前项目更新

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1822421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:17:10  来源:igfitidea点击:

IsSynchronizedWithCurrentItem attribute and current item updates

wpfdata-bindingselecteditemitemssource

提问by Berryl

I have a view model to manage a dialog type of view that allows filtering of a listing (if necessary) and selection of an item. The code works fine whether I set IsSynchronizedWithCurrentItem to true or not. My understanding is that this property is not true by default in a ListView, so I'd like to better understand this property.

我有一个视图模型来管理对话框类型的视图,该视图允许过滤列表(如有必要)和选择项目。无论我是否将 IsSynchronizedWithCurrentItem 设置为 true,代码都可以正常工作。我的理解是这个属性在 ListView 中默认不是真的,所以我想更好地理解这个属性。

Here is the binding setup in the view's xaml (which works just as well without the synch property setting):

这是视图的 xaml 中的绑定设置(在没有同步属性设置的情况下也能正常工作):

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

The view model Projects is actually a CollectionViewSource that is backed by a private ObservableCollection. I think I glommed this idea from a sample project of Josh Smith's, but I honestly don't recall right now. Here is the relevant portion of the VM that relates to the xaml binding:

视图模型项目实际上是一个由私有 ObservableCollection 支持的 CollectionViewSource。我想我从 Josh Smith 的一个示例项目中想到了这个想法,但老实说我现在不记得了。这是与 xaml 绑定相关的 VM 的相关部分:

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; }

The Filter property of the CollectionViewSource has a handler which returns various predicates on the view model items in the list which is picked up by the bindings correctly. Here is the gist of that code (which is in the same ProjectSelctionViewModel):

CollectionViewSource 的 Filter 属性有一个处理程序,它返回列表中视图模型项的各种谓词,这些谓词由绑定正确拾取。这是该代码的要点(在同一个 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;
    }

Setting the Mode=TwoWay is redundant since the ListView's SelectedItem binding is two way by default, but I don't mind being explicit about it (I might feel differently about that once I understand WPF better).

设置 Mode=TwoWay 是多余的,因为 ListView 的 SelectedItem 绑定默认是两种方式,但我不介意明确说明它(一旦我更好地理解 WPF,我可能会有不同的感觉)。

What about my code is making the IsSynchronizedWithCurrentItem=True redundant?

我的代码使 IsSynchronizedWithCurrentItem=True 变得多余怎么办?

My gut is that this is decent code, but I don't like that pieces of it seem to be working via "magic", which means I would welcome any constructive feedback!

我的直觉是这是一个不错的代码,但我不喜欢它的一部分似乎是通过“魔法”工作的,这意味着我欢迎任何建设性的反馈!

Cheers,
Berryl

干杯,
贝瑞尔

回答by H.B.

IsSynchronizedWithCurrentItemsyncs the CurrentItemof the default CollectionViewof the bound collection with the SelectedItemof your control.

IsSynchronizedWithCurrentItem将绑定集合CurrentItem的默认值CollectionViewSelectedItem您的控件同步。

Since you never use the CurrentItemof the CollectionViewand you do not appear to bind to the same collection twice setting the property in question has no visible effect at all.

由于您从不使用CurrentItemofCollectionView并且您似乎没有两次绑定到同一个集合,因此设置有问题的属性根本没有可见的效果。



Demo of how the property syncs (for XAML viewers like Kaxamlor XAMLPad):

属性同步方式的演示(适用于Kaxaml或 XAMLPad等 XAML 查看器):

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