首先,我会英语。所以,如果您说您听不懂,我感到很抱歉。
我有2个ListBox的WPF应用程序。我想将应用程序重新制作为MVVM。
但是我不知道将SelectionChanged事件编码为MVVM。
我尝试了这段代码。
在查看代码中,它包含注释。我添加的代码然后得到了我朋友的建议。 (但它也不起作用。)
//查看
xmlns:xcad="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox HorizontalAlignment="Left" Height="56" Margin="64,67,0,0" VerticalAlignment="Top" Width="380" SelectedItem="{Binding SelectColorList}" ItemsSource="{Binding ColorList}"/>
<ListBox HorizontalAlignment="Left" Height="56" Margin="64,182,0,0" VerticalAlignment="Top" Width="380" ItemsSource="{Binding ItemList}"/>
<!--<xcad:CheckListBox HorizontalAlignment="Left" Height="56" Margin="64,67,0,0" VerticalAlignment="Top" Width="380" SelectedItemsOverride="{Binding SelectColorList}" ItemsSource="{Binding ColorList}"/>
<xcad:CheckListBox HorizontalAlignment="Left" Height="56" Margin="64,182,0,0" VerticalAlignment="Top" Width="380" ItemsSource="{Binding ItemList}"/>-->
<Label Content="Color" HorizontalAlignment="Left" Height="24" Margin="65,38,0,0" VerticalAlignment="Top" Width="65"/>
<Label Content="Item" HorizontalAlignment="Left" Height="24" Margin="64,153,0,0" VerticalAlignment="Top" Width="65"/>
</Grid>
// CodeBehinde
private MainViewModel viewmodel;
public MainWindow()
{
InitializeComponent();
viewmodel = new MainViewModel();
this.DataContext = viewmodel;
}
// ViewModel
public class MainViewModel : INotifyPropertyChanged
{
private ObservableCollection<string> ColorListVal;
public ObservableCollection<string> ColorList
{
get { return ColorListVal; }
set
{
ColorListVal = value;
NotifyPropertyChanged("ColorList");
}
}
private ObservableCollection<string> SelectColorListVal = new ObservableCollection<string>();
public ObservableCollection<string> SelectColorList
{
get { return SelectColorListVal; }
set
{
SelectColorListVal = value;
NotifyPropertyChanged("SelectColorList");
ItemListVal.Clear();
for (int i = 0; i < SelectColorList.Count; i++)
{
switch (SelectColorList[i])
{
case "red":
ItemListVal.Add("apple");
ItemListVal.Add("sun");
break;
case "blue":
ItemListVal.Add("sea");
ItemListVal.Add("sky");
break;
case "yellow":
ItemListVal.Add("lemmon");
ItemListVal.Add("pineapple");
break;
case "green":
ItemListVal.Add("vegetable");
ItemListVal.Add("greentea");
break;
}
}
}
}
private ObservableCollection<string> ItemListVal;
public ObservableCollection<string> ItemList
{
get { return ItemListVal; }
set
{
ItemListVal = value;
NotifyPropertyChanged("ItemList");
}
}
public MainViewModel()
{
ColorListVal = new ObservableCollection<string>() { "red", "blue", "yellow", "green" };
ItemListVal = new ObservableCollection<string>() { "not selected!" };
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
我想做这些...
@如果单击“红色”,则项目列表将ListBox显示为“ apple”和“ sun”。然后,如果我单击蓝色...是相同的。
@我要单击许多颜色!因此,如果我单击红色和蓝色,则项目列表会显示“苹果”,“太阳”,“海洋”和“天空”。 (但我不在乎列表顺序)
@列表(颜色和项目)内容不同。所以我想将内容设置为动态,并将项目添加为动态。
我应该重新制作这段代码吗?
答案 0 :(得分:2)
在Xaml中,您需要将SelectedItem属性绑定到字符串(而不是列表/集合)
<ListBox SelectedItem="{Binding SelectColor}" ItemsSource="{Binding ColorList}"/>
<ListBox ItemsSource="{Binding ItemList}"/>
ViewModel,
private string _selectedColor;
public string SelectedColor
{
get => _selectedColor;
set
{
_selectedColor = value;
ItemList.Clear();
switch (_selectedColor)
{
case "red":
ItemList.Add("apple");
ItemList.Add("sun");
break;
…
}
NotifyPropertyChanged(nameof(SelectedColor));
}
我还建议在从集合中添加/删除项目时,使用ItemList
代替ItemListVal
(后备字段)。
答案 1 :(得分:1)
在您的xaml文件中,将SelectedItem绑定到作为集合的SelectColorList,要使其正确,应将其绑定到单个值(在您的情况下为某些字符串属性),而不是集合。
更新:
首先,我想提到无法进行多重绑定,这就是为什么我们将使用事件SelectionChanged的原因。
例如,这是您的“视图”,其中包含两个列表框,其中一个将包含颜色源,该颜色源可以进行多种选择:
<Window x:Class="WpfApp1.MainWindow">
<StackPanel Orientation="Horizontal">
<!-- First list box contains colors -->
<ListBox
ItemsSource="{Binding ColorList}"
SelectionMode="Extended"
SelectionChanged="ListBox_SelectionChanged"
/>
<!-- Second list box will contain result values -->
<ListBox
ItemsSource="{Binding ItemList}"
/>
</StackPanel>
</Window>
您的MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Set data context
DataContext = new ViewModel();
}
/// <summary>
/// Called when selection is changed
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
// Get event sender
var listBox = sender as ListBox;
// Create temp list for selected items
var tempList = new List<string>();
foreach (string item in listBox.SelectedItems)
{
tempList.Add(item);
}
(DataContext as ViewModel).OnSelectionChanged(tempList);
}
}
最后,您的视图模型:
public class ViewModel : INotifyPropertyChanged
{
#region Private Fields
private ObservableCollection<string> mColorList;
private ObservableCollection<string> mItemList;
#endregion
#region Public Properties
/// <summary>
/// This is list box 1 items source with colors
/// </summary>
public ObservableCollection<string> ColorList
{
get { return mColorList; }
set
{
mColorList = value;
NotifyPropertyChanged(nameof(ColorList));
}
}
/// <summary>
/// This is list box 2 items with results
/// </summary>
public ObservableCollection<string> ItemList
{
get { return mItemList; }
set
{
mItemList = value;
NotifyPropertyChanged(nameof(ItemList));
}
}
#endregion
#region Constructor
public ViewModel()
{
// Initialization
ColorList = new ObservableCollection<string>() { "red", "blue", "yellow", "green" };
ItemList = new ObservableCollection<string>() { "not selected!" };
}
#endregion
#region Public Methods
/// <summary>
/// Called when selection is changed
/// </summary>
/// <param name="selectedItems"></param>
public void OnSelectionChanged(IEnumerable<string> selectedItems)
{
ItemList.Clear();
foreach (var item in selectedItems)
{
switch (item)
{
case "red":
ItemList.Add("apple");
ItemList.Add("sun");
break;
case "blue":
ItemList.Add("sea");
ItemList.Add("sky");
break;
}
}
}
#endregion
#region InterfaceImplementation
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
这就是完成的方法。希望这个答案对您有帮助