前言
wpf中ListBox在针对多个选项选择中的应用十分广泛,本文就来讲解非Mvvm和Mvvm模式下如何使用ListBox。
1、非MVVM模式下
xaml代码:
ListBoxItem用于存储ListBox的每一项,可以设置ListBoxItem的属性,比如Foreground控制项的字体颜色;Background来控制项的背景色;为ListBox注册SelectionChanged事件,该事件代码在MainWindow窗体类中。
cpp
<ListBox x:Name="ListBox_test" SelectionChanged="ListBox_SelectionChanged">
<ListBoxItem Foreground="White" Background="Red" >项目1</ListBoxItem>
<ListBoxItem>项目2</ListBoxItem>
<ListBoxItem>项目3</ListBoxItem>
<ListBoxItem>项目4</ListBoxItem>
</ListBox >
MainWindow窗体类
csharp
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = ListBox_test.SelectedItem;
}
}
运行结果:
2、MVVM模式下
2.1 SelectionMode为Single
xaml代码:
1)mvvm模式下使用绑定来为ListBox添加数据,通过为ItemsSource绑定ViewModel中的Items属性
2)然后为了获取ListBox中用户选择的哪一项,为SelectedItem绑定ViewModel中的divisionType属性
但是由于SelectedItem是object类型,divisionType是枚举类型,无法直接绑定,所以要使用类型转换
csharp
<Window.Resources>
<local:DivisionTypeToString x:Key="DivisionTypeToString"/>
</Window.Resources>
<ListBox SelectionMode="Single" ItemsSource="{Binding Items }" Foreground="Red" SelectedItem="{Binding divisionType, Converter={StaticResource DivisionTypeToString}}" >
</ListBox >
添加类型转换
下面的Convert方法用于将DivisionType转换成字符串,ConvertBack用于将字符串转换成DivisionType
csharp
public class DivisionTypeToString: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
DivisionType divisionType = (DivisionType)value;
return divisionType.ToString ();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
DivisionType divisionType =(DivisionType)Enum.Parse(typeof (DivisionType),value .ToString ());
return divisionType;
}
}
添加 Model类
csharp
public enum DivisionType
{
分时1,
分时2
}
添加ViewModelBase类
csharp
public class ViewModelBase
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propname));
}
}
}
添加ViewModel类
csharp
public class ViewModel : ViewModelBase
{
public ViewModel()
{
Items = new List<string>();
Items.Add("分时1");
Items.Add("分时2");
}
private List<string> items;
public List<string> Items
{
get
{
return items;
}
set
{
this.items = value;
OnPropertyChanged("Items");
}
}
private DivisionType _divisionType = DivisionType.分时1;
public DivisionType divisionType
{
get
{
return _divisionType;
}
set
{
this._divisionType = value;
OnPropertyChanged("divisionType");
}
}
}
运行结果:
2.2 SelectionMode为Multiple
xaml代码:
1)mvvm模式下使用绑定来为ListBox添加数据,通过为ItemsSource绑定ViewModel中的Items属性
2)又因为是多选,所以不能使用SelectedItem属性的绑定,得使用 SelectionChanged事件,然后在事件中获取SelectedItems属性从而获取所有用户选择的项,所以这里使用使用Interaction.Trigger,EventName指定绑定的事件名称,CommandSelectionChanged是绑定的ViewModel中的命令。(这里要注意使用Interaction.Triggers需要引用System.Windows.Interactivity.dll)
csharp
<Window.Resources>
<local:DivisionTypeToString x:Key="DivisionTypeToString"/>
</Window.Resources>
<ListBox x:Name="listBox_test2" SelectionMode="Multiple" ItemsSource="{Binding Items }" Foreground="Red" >
<Event:Interaction.Triggers>
<Event:EventTrigger EventName="SelectionChanged">
<Event:InvokeCommandAction Command="{Binding CommandSelectionChanged}" CommandParameter="{Binding ElementName=listBox_test2}"/>
</Event:EventTrigger>
</Event:Interaction.Triggers>
</ListBox >
添加DelegateCommand
csharp
public class DelegateCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (_canExecute != null)
{
return _canExecute(parameter);
}
else
{
return true;
}
}
public void Execute(object parameter)
{
_execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
}
添加 Model类
csharp
public enum DivisionType
{
分时1,
分时2
}
添加ViewModelBase类
csharp
public class ViewModelBase
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propname));
}
}
}
添加ViewModel类
csharp
public class ViewModel : ViewModelBase
{
public ICommand CommandSelectionChanged { get; set; }
public ViewModel()
{
Items = new List<string>();
Items.Add("分时1");
Items.Add("分时2");
CommandSelectionChanged = new DelegateCommand(ListBoxSelectionChanged);
}
private List<string> items;
public List<string> Items
{
get
{
return items;
}
set
{
this.items = value;
OnPropertyChanged("Items");
}
}
private ObservableCollection<DivisionType> _divisionTypeList = new ObservableCollection<DivisionType>();
public ObservableCollection<DivisionType> divisionTypeList
{
get
{
return _divisionTypeList;
}
set
{
this._divisionTypeList = value;
OnPropertyChanged("divisionTypeList");
}
}
private void ListBoxSelectionChanged(object obj)
{
divisionTypeList.Clear();
ListBox listBox =(ListBox) obj;
foreach ( var item in listBox.SelectedItems)
{
DivisionType divisionType=(DivisionType) Enum.Parse(typeof (DivisionType),item.ToString ());
divisionTypeList.Add(divisionType);
}
}
}
运行结果: