从列表框中获取选中的项目

时间:2019-01-08 10:17:19

标签: c# wpf checkbox mvvm viewmodel

我刚刚习惯了MVVM,想在没有代码隐藏的情况下进行操作,并在视图模型中定义所有内容。 组合框代表几个选择选项(有效)。我想查询已检查的元素。 不幸的是我无法访问它们。文本框应将所有选定的元素显示为串联字符串。

视图模型

class MainViewModel : BaseViewModel
    {
        #region Fields

        private ObservableCollection<EssayTypeViewModel> _essayTypes;
        private EssayTypeViewModel _selectedEssayTypes;

        #endregion


        public ObservableCollection<EssayTypeViewModel> EssayTypes
        {
            get => _essayTypes;
            set
            {
                if (_essayTypes == value) return;
                _essayTypes = value; OnPropertyChanged("EssayTypes");
            }
        }


        public EssayTypeViewModel SelectedEssayTypes
        {
            get => _selectedEssayTypes;
            set { _selectedEssayTypes = value; OnPropertyChanged("SelectedEssayTypes"); }
        }


        public MainViewModel()
        {

            // Load Essay Types
            EssayTypeRepository essayTypeRepository = new EssayTypeRepository();
            var essayTypes = essayTypeRepository.GetEssayTypes();
            var essayTypeViewModels = essayTypes.Select(m => new EssayTypeViewModel()
            {
                Text = m.Text
            });

            EssayTypes = new ObservableCollection<EssayTypeViewModel>(essayTypeViewModels);

        }
    }

XAML

<ListBox x:Name="Listitems" SelectionMode="Multiple" Height="75" Width="200" ItemsSource="{Binding EssayTypes}" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox Content="{Binding Text}" IsChecked="{Binding Checked}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

    <TextBox Text="{Binding Path=SelectedEssayTypes}" Grid.Column="0" Width="160" Height="25" Margin="0,140,0,0"/>

3 个答案:

答案 0 :(得分:2)

您可以将事件处理程序关联到PropertyChanged集合中所有EssayTypeViewModel对象的EssayTypes事件,并引发PropertyChanged事件以获取只读属性MainViewModel会将所有选定的元素作为连接字符串返回:

public MainViewModel()
{
    // Load Essay Types
    EssayTypeRepository essayTypeRepository = new EssayTypeRepository();
    var essayTypes = essayTypeRepository.GetEssayTypes();
    var essayTypeViewModels = essayTypes.Select(m =>
    {
        var vm = EssayTypeViewModel()
        {
            Text = m.Text
        };
        vm.PropertyChanged += OnPropertyChanged;
        return vm;
    });

    EssayTypes = new ObservableCollection<EssayTypeViewModel>(essayTypeViewModels);
}

private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "Checked")
        OnPropertyChanged("SelectedItems");
}

public string SelectedItems => string.Join(",", EssayTypes.Where(x => x.Checked).ToArray());

这需要EssayTypeViewModel类实现INotifyPropertyChanged接口(例如,从您的BaseViewModel类派生)。

答案 1 :(得分:1)

您可以在复选框绑定上应用“模式=双向”。

<CheckBox Content="{Binding Text}" IsChecked="{Binding Checked, Mode=TwoWay}"/>

然后,您可以遍历论文类型集合以检查是否已检查项目条目。

例如示例代码可以是:

foreach (var essayTypeInstance in EssayTypes)
{
     if(essayTypeInstance.Checked)
     {
          // this value is selected
     }
}

希望这会有所帮助。

答案 2 :(得分:0)

mm8答案有效。同时,我想出了另一种方法。并非100%兼容MVVM,但它可以工作并且非常简单。

XAML

<ListBox x:Name="ListItems" SelectionMode="Multiple" Height="75" Width="200" ItemsSource="{Binding CollectionOfItems}" >
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox Content="{Binding Name}" IsChecked="{Binding Checked, Mode=TwoWay}" Unchecked="GetCheckedElements" Checked="GetCheckedElements" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <TextBox Text="{Binding SelectedItemsString, UpdateSourceTrigger=PropertyChanged}" Grid.Column="0" Width="160" Height="25" Margin="0,140,0,0"/>

隐藏代码

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel();
        }


        private void GetCheckedElements(object sender, RoutedEventArgs e)
        {
            (DataContext as MainViewModel)?.FindCheckedItems();
            (DataContext as MainViewModel)?.ConcatSelectedElements();
        }

    }

模型

public class Items
    {
        public bool Checked { get; set; }
        public string Name { get; set; }

    }

ItemsViewModel (BaseViewModel仅实现INotifyPropertyChanged)

class ItemsViewModel : BaseViewModel
    {
        private bool _checked;
        private string _name;

        public bool Checked
        {
            get => _checked;
            set
            {
                if (value == _checked) return;

                _checked = value;
                OnPropertyChanged("Checked");
            }
        }

        public string Name
        {
            get => _name;
            set
            {
                if (value == _name) return;

                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }

MainViewModel

public class MainViewModel : BaseViewModel
    {
        private string _selectedItemsString;
        private ObservableCollection<Items> _selectedItems;



        public ObservableCollection<Items> CollectionOfItems { get; set; }

        public ObservableCollection<Items> SelectedItems
        {
            get => _selectedItems;
            set
            {
                _selectedItems = value;
                OnPropertyChanged("SelectedItems");
            } 
        }


        public string SelectedItemsString
        {
            get => _selectedItemsString;
            set
            {
                if (value == _selectedItemsString) return;

                _selectedItemsString = value;
                OnPropertyChanged("SelectedItemsString");
            }
        }

        public MainViewModel()
        {
            CollectionOfItems = new ObservableCollection<Items>();
            SelectedItems = new ObservableCollection<Items>();




            CollectionOfItems.Add(new Items { Checked = false, Name = "Item 1" });
            CollectionOfItems.Add(new Items { Checked = false, Name = "Item 2" });
            CollectionOfItems.Add(new Items { Checked = false, Name = "Item 3" });

        }


        public void FindCheckedItems()
        {
            CollectionOfItems.Where(x => x.Checked).ToList().ForEach(y => SelectedItems.Add(y));
        }


        public void ConcatSelectedElements()
        {
            SelectedItemsString = string.Join(", ", CollectionOfItems.Where(x => x.Checked).ToList().Select(x => x.Name)).Trim();
        }
    }