【问题标题】:Get checked items from a listbox从列表框中获取选中的项目
【发布时间】:2019-06-03 00:25:26
【问题描述】:

我刚刚习惯了 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"/>

【问题讨论】:

  • “文本框应该将所有选定的元素显示为连接字符串” - 最难的部分是在必须重新评估绑定时通知TextBoxSelectedEssayTypes 可以是一个简单的 getter-only 属性,它加入 EssayTypes.Where(o =&gt; o.Checked)。如果您在后面的代码中创建项目,然后考虑在内部传递主窗口视图模型实例(例如作为构造函数参数),那么每个项目都可以在Checked setter 中发出通知。

标签: c# wpf checkbox mvvm viewmodel


【解决方案1】:

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

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 类派生)。

【讨论】:

    【解决方案2】:

    您可以在复选框绑定上应用 Mode = Two way。

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

    然后你可以遍历essay types集合来检查item entry是否被选中。

    例如。示例代码可以是:

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

    希望这会有所帮助。

    【讨论】:

    • 太快了!但是,物业如何知道某个项目已被检查?使用后面的代码,我将组合框绑定到一个事件并强制发送者检索所有检查的值。但是没有任何代码,我不知道如何宣布某些事情发生了变化。
    • 由于双向绑定,这将自动发生。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2015-10-20
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-09
      • 2014-10-14
      • 1970-01-01
      相关资源
      最近更新 更多