【问题标题】:ListBox Selected Items in WPF using MVVM使用 MVVM 在 WPF 中的 ListBox Selected Items
【发布时间】:2015-05-14 13:14:28
【问题描述】:

我在 WPF 中有一个 ListBox,它里面有 CheckBox 项目。我在 XAML 代码隐藏中使用以下代码拆分选中的复选框。

StringBuilder sbMonths = new StringBuilder();
StringBuilder sbMonthNames = new StringBuilder();

string months;
string monthNames;

foreach (var item in ListBox.Items)
{
    if (item is CheckBox)
    {
        var chk = item as CheckBox;

        if ((bool)chk.IsChecked)
        {
            sbMonths.Append(chk.Tag);
            sbMonths.Append(',');

            sbMonthNames.Append(chk.Content.ToString());
            sbMonthNames.Append('-');
        }
    }

}

months = sbMonths.ToString();
monthNames = sbMonthNames.ToString();
int lastIndexOfMonths = months.LastIndexOf(',');
int lastIndexOfMonthNames = monthNames.LastIndexOf('-');

if (lastIndexOfMonths > -1)
{
    months = months.Remove(lastIndexOfMonths);
    monthNames = monthNames.Remove(lastIndexOfMonthNames);
    .... I do more here
}

问题是我不知道如何使用 MVVM 来做到这一点。您能提供一些解决方案吗?

XAML:

<ListBox Name="ListBox" HorizontalAlignment="Left" Height="149" Margin="23,47,0,0" VerticalAlignment="Top" Width="210">
    <ComboBoxItem Content="-- Ay Seçiniz --"/>
    <CheckBox Content="Ocak" Tag="1"/>
    <CheckBox Content="Şubat" Tag="2"/>
    <CheckBox Content="Mart" Tag="3"/>
    <CheckBox Content="Nisan" Tag="4"/>
    <CheckBox Content="Mayıs" Tag="5"/>
    <CheckBox Content="Haziran" Tag="6"/>
    <CheckBox Content="Temmuz" Tag="7"/>
    <CheckBox Content="Ağustos" Tag="8"/>
    <CheckBox Content="Eylül" Tag="9"/>
    <CheckBox Content="Ekim" Tag="10"/>
    <CheckBox Content="Kasım" Tag="11"/>
    <CheckBox Content="Aralık" Tag="12"/>
</ListBox>

【问题讨论】:

标签: wpf mvvm


【解决方案1】:

使用以下代码:

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox ItemsSource="{Binding Months}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Content="{Binding MonthName}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Printing;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainViewModel();
        }
    }

    public class MainViewModel : BaseViewModel
    {
        public ObservableCollection<MonthViewModel> Months { get; set; }

        public MainViewModel()
        {
            this.Months = new ObservableCollection<MonthViewModel>();

            this.Months.Add(new MonthViewModel() { MonthName = "Ocak", MonthNumber = 1 });
            this.Months.Add(new MonthViewModel() { MonthName = "Şubat", MonthNumber = 2 });
            this.Months.Add(new MonthViewModel() { MonthName = "Mart", MonthNumber = 3 });
            this.Months.Add(new MonthViewModel() { MonthName = "Nisan", MonthNumber = 4 });
            this.Months.Add(new MonthViewModel() { MonthName = "Mayıs", MonthNumber = 5 });
            this.Months.Add(new MonthViewModel() { MonthName = "Haziran", MonthNumber = 6 });
            this.Months.Add(new MonthViewModel() { MonthName = "Temmuz", MonthNumber = 7 });
            this.Months.Add(new MonthViewModel() { MonthName = "Ağustos", MonthNumber = 8 });
            this.Months.Add(new MonthViewModel() { MonthName = "Eylül", MonthNumber = 9 });
            this.Months.Add(new MonthViewModel() { MonthName = "Ekim", MonthNumber = 10 });
            this.Months.Add(new MonthViewModel() { MonthName = "Kasım", MonthNumber = 11 });
            this.Months.Add(new MonthViewModel() { MonthName = "Aralık", MonthNumber = 12 });
        }
    }

    public class MonthViewModel : BaseViewModel
    {
        private string _monthName;
        public string MonthName
        {
            get { return _monthName; }
            set
            {
                if (_monthName != value)
                {
                    _monthName = value;
                    this.NotifyOnPropertyChange(() => this.MonthName);
                }
            }
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (_isSelected != value)
                {
                    _isSelected = value;
                    this.NotifyOnPropertyChange(() => this.IsSelected);
                }
            }
        }

        private int _monthNumber;
        public int MonthNumber
        {
            get { return _monthNumber; }
            set
            {
                if (_monthNumber != value)
                {
                    _monthNumber = value;
                    this.NotifyOnPropertyChange(() => this.MonthNumber);
                }
            }
        }
    }

    public class BaseViewModel : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyOnPropertyChange(Expression<Func<object>> expression)
        {
            if (PropertyChanged != null)
            {
                if (expression.NodeType != ExpressionType.Lambda)
                    throw new ArgumentException("Value must be a lamda expression", "expression");

                var body = expression.Body as MemberExpression;

                if (body == null)
                {
                    throw new ArgumentException("'expression' should have a Body of type MemberExpression");
                }

                string propertyName = body.Member.Name;
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

        }
        #endregion
    }
}

ViewModel 中的任何时间点使用上述代码,您将能够从集合Months 中获取所选项目,并且您可以根据需要应用您的代码。

【讨论】:

    【解决方案2】:

    这是使用 MVVM 执行此操作的方法。

    首先,为您的月份创建一个模型 (MVVM)。

    public class Month
    {
        public string Name {get;set;}
        public int Index {get;set;} // or whatever else you need
        public bool Selected {get;set;}
    }
    

    现在,您希望将 ViewModel (MVVM) 中的那些都作为所有月份的集合公开。

    public class ViewModel
    {
        // init this in your ctor
        public ObservableCollection<Month> Months {get;private set;}
        // snip
    

    然后在你的视图中绑定它们(MVVM)

    <ListBox ItemsSource="{Binding Months}"> 
        <ListBox.ItemTemplate>
          <DataTemplate>
              <CheckBox IsChecked="{Binding Selected}" Content="{Binding Name}"/>
          </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    这就是 MVVM 的工作原理

    【讨论】:

    • 确实如此。这不是 MVVM。但我需要在 MVVM 中进行;)这就是我问的原因。所以,我应该像month1、month2一样单独创建12个月。然后我将添加到 Months 可观察集合中。就这些吗?
    • @Samet 好吧,你去吧!一个简单的 MVVM 实现。您必须弄清楚是什么触发了您的日期操作代码并将其转换为等效的 MVVM 范例......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 2010-09-28
    • 2011-05-09
    • 1970-01-01
    • 2013-05-08
    相关资源
    最近更新 更多