简体   繁体   English

ListBox 中的选定项实现在 WPF 和 MVVM 中表现得很奇怪

[英]Selected Items implementation in a ListBox acts odd in WPF and MVVM

I made quite research to implement selected items via MVVM in WPF.我做了相当多的研究,以通过 WPF 中的 MVVM 实现选定的项目。 I thought I had success but now the selection is made according to scroll position.我以为我成功了,但现在选择是根据滚动位置进行的。 I select all items in the listbox but only first 11 marked as selected.我选择了列表框中的所有项目,但只有前 11 个标记为选中。 If I scroll more, more selected.如果我滚动更多,选择更多。 If I scroll to the bottom all items selected.如果我滚动到底部所有选定的项目。 Is there solution for this problem?这个问题有解决方案吗?

XAML: XAML:

 <ListBox x:Name="DataListBox" SelectionMode="Extended" HorizontalAlignment="Left" Margin="5,5,0,0" Grid.Row="1" Grid.Column="0" Grid.RowSpan="8" VerticalAlignment="Top" Height="200" Width="200" ItemsSource="{Binding DataListBoxItemsSource, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding DataListBoxSelectedItem, UpdateSourceTrigger=PropertyChanged}" > <ListBox.InputBindings> <KeyBinding Command="ApplicationCommands.SelectAll" Modifiers="Ctrl" Key="A" /> </ListBox.InputBindings> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property="IsSelected" Value="{Binding IsSelected}"/> </Style> </ListBox.ItemContainerStyle> <i:Interaction.Triggers> <i:EventTrigger EventName="SelectionChanged" > <i:CallMethodAction TargetObject="{Binding}" MethodName="DataListBox_SelectionChanged"/> </i:EventTrigger> </i:Interaction.Triggers> </ListBox>

View Model查看模型

        public async void CreateLayersTOC()
    {
        if (MapView.Active != null)
        {
            if (DataListBoxSelectedItem != null || FavoriteTabsSelectedItem != null)
                MainStackPanelIsEnabled = false;
            LayerNames = new List<string>();
            await Task.Run(() =>
            {
                MessageBox.Show("source count " + DataListBoxItemsSource.Count);//58 items all selected
                if (DataListBoxSelectedItem != null)
                    foreach (ItemPresenter itemP in DataListBoxItemsSource)
                    {
                        if (itemP.IsSelected)
                        {
                            if (LayerNames.Contains(itemP.ToString()) == false)
                                LayerNames.Add(itemP.ToString());
                        }

                    }

                if (FavoriteTabsSelectedItem != null)
                {
                    foreach (ItemPresenter itemP in FavListBoxItemsSource)
                    {
                        if (itemP.IsSelected)
                        {
                            if (LayerNames.Contains(itemP.ToString()) == false)
                                LayerNames.Add(itemP.ToString());
                        }
                    }
                }

                MessageBox.Show("Coll" + LayerNames.Count);//Count depends on scroll position
            });

            //do stuff
        }
        else
            MessageBox.Show("Make sure to have a map available before adding layers to a map");
        MainStackPanelIsEnabled = true;
    }

 public class ItemPresenter : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private readonly string _value;

        public ItemPresenter(string value)
        {
            _value = value;
        }

        public override string ToString()
        {
            return _value;
        }

        private bool _isSelected;

        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (_isSelected != value)
                {
                    _isSelected = value;
                    OnPropertyChanged();
                }
            }
        }
    }

Here is a simple example of everything that is necessary to bind the SelectedItem of a ListBox and the IsSelected property of the ListBoxItems.下面是绑定 ListBox 的 SelectedItem 和 ListBoxItems 的 IsSelected 属性所需的一切的简单示例。

XAML: XAML:

<ListBox ItemsSource="{Binding Items}"
         SelectedItem="{Binding SelectedItem}"
         SelectionMode="Extended">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="IsSelected" Value="{Binding Selected}"/>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

View Model:查看型号:

public class DataItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Name { get; set; }

    private bool selected;

    public bool Selected
    {
        get { return selected; }
        set
        {
            selected = value;
            PropertyChanged?.Invoke(this,
                new PropertyChangedEventArgs(nameof(Selected)));

            Debug.WriteLine(Name + " selected: " + selected);
        }
    }
}

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<DataItem> Items { get; }
        = new ObservableCollection<DataItem>();

    public IEnumerable<DataItem> SelectedItems
    {
        get { return Items.Where(i => i.Selected); }
    }

    private DataItem selectedItem;

    public DataItem SelectedItem
    {
        get { return selectedItem; }
        set
        {
            selectedItem = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItem)));
        }
    }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var vm = new ViewModel();
        vm.Items.Add(new DataItem { Name = "Item 1" });
        vm.Items.Add(new DataItem { Name = "Item 2" });
        vm.Items.Add(new DataItem { Name = "Item 3" });
        vm.Items.Add(new DataItem { Name = "Item 4" });
        vm.Items.Add(new DataItem { Name = "Item 5" });

        DataContext = vm;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM