WPF 使用附加屬性來繫結ListBox的SelectedItems
阿新 • • 發佈:2022-04-21
ListBox的SelectedItems屬性是隻讀屬性,沒法直接繫結。
一般的處理方式是在命令中通過命令引數傳遞到ViewModel裡面。
現在通過附加屬性來解決這個問題
效果
後臺程式碼
1 using Microsoft.Toolkit.Mvvm.ComponentModel; 2 using Microsoft.Toolkit.Mvvm.Input; 3 using System; 4 using System.Collections; 5 using System.Collections.Generic; 6 using System.Collections.ObjectModel;7 using System.Linq; 8 using System.Text; 9 using System.Threading.Tasks; 10 using System.Windows; 11 using System.Windows.Controls; 12 using System.Windows.Controls.Primitives; 13 using System.Windows.Input; 14 15 namespace MvvmToolkit學習 16 { 17 public class DataItem 18 { 19public ObservableCollection<string> Data { get; set; } 20 21 public string Name { get; set; } 22 23 public DataItem() 24 { 25 Data = new ObservableCollection<string>(); 26 Data.Add("Sun"); 27 Data.Add("Moon");28 Data.Add("Star"); 29 } 30 } 31 32 public class ListBoxHelper 33 { 34 // Using a DependencyProperty as the backing store for SelectedItems. This enables animation, styling, binding, etc... 35 public static readonly DependencyProperty SelectedItemsProperty = 36 DependencyProperty.RegisterAttached("SelectedItems", 37 typeof(IList), 38 typeof(ListBoxHelper), 39 new FrameworkPropertyMetadata(default(IList), 40 FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 41 OnSelectedItemsChanged)); 42 43 public static IList GetSelectedItems(DependencyObject obj) 44 { 45 return (IList)obj.GetValue(SelectedItemsProperty); 46 } 47 48 public static void SetSelectedItems(DependencyObject obj, IList value) 49 { 50 obj.SetValue(SelectedItemsProperty, value); 51 } 52 53 private static void OnlistBoxSelectionChanged(object sender, SelectionChangedEventArgs e) 54 { 55 IList dataSource = GetSelectedItems(sender as DependencyObject); 56 //新增使用者選中的當前項. 57 foreach (var item in e.AddedItems) 58 { 59 dataSource.Add(item); 60 } 61 //刪除使用者取消選中的當前項 62 foreach (var item in e.RemovedItems) 63 { 64 dataSource.Remove(item); 65 } 66 } 67 68 private static void OnSelectedItemsChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 69 { 70 var listBox = target as ListBox; 71 if ((listBox != null) && (listBox.SelectionMode == SelectionMode.Multiple)) 72 { 73 if (e.OldValue != null) 74 { 75 listBox.SelectionChanged -= OnlistBoxSelectionChanged; 76 } 77 IList collection = e.NewValue as IList; 78 listBox.SelectedItems.Clear(); 79 if (collection != null) 80 { 81 foreach (var item in collection) 82 { 83 listBox.SelectedItems.Add(item); 84 } 85 listBox.SelectionChanged += OnlistBoxSelectionChanged; 86 } 87 } 88 } 89 } 90 91 internal class Test1ViewModel : ObservableObject 92 { 93 private RelayCommand addCmd; 94 95 public ICommand AddCmd 96 { 97 get 98 { 99 if (addCmd == null) 100 { 101 addCmd = new RelayCommand(PerformAddCmd); 102 } 103 104 return addCmd; 105 } 106 } 107 108 public ObservableCollection<DataItem> DataItems { get; set; } 109 public List<DataItem> SelectedItems { get; set; } 110 public double Size { get; set; } 111 112 public Test1ViewModel() 113 { 114 SelectedItems = new List<DataItem>();//此處屬性必須賦值,不可為null。。繞了很久的彎路 115 DataItems = new ObservableCollection<DataItem>(); 116 DataItems.Add(new DataItem() { Name = "A" }); 117 DataItems.Add(new DataItem() { Name = "B" }); 118 } 119 120 private void PerformAddCmd() 121 { 122 MessageBox.Show(string.Join("", SelectedItems.Select(s => s.Name))); 123 } 124 } 125 }
xaml
1 <Window 2 x:Class="MvvmToolkit學習.Test1" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:local="clr-namespace:MvvmToolkit學習" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 xmlns:pu="clr-namespace:Panuon.UI.Silver;assembly=Panuon.UI.Silver" 9 Title="Test1" 10 Width="800" 11 Height="450" 12 d:DataContext="{d:DesignInstance Type={x:Type local:Test1ViewModel}}" 13 mc:Ignorable="d"> 14 <Grid> 15 <StackPanel Orientation="Vertical"> 16 <ListBox 17 Width="200" 18 Height="100" 19 local:ListBoxHelper.SelectedItems="{Binding SelectedItems}" 20 ItemsSource="{Binding DataItems}" 21 SelectionMode="Multiple"> 22 <ListBox.ItemTemplate> 23 <DataTemplate DataType="{x:Type local:DataItem}"> 24 <StackPanel Orientation="Horizontal"> 25 <CheckBox IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"/> 26 <ContentControl Content="{Binding}"/> 27 </StackPanel> 28 </DataTemplate> 29 </ListBox.ItemTemplate> 30 </ListBox> 31 32 <Button 33 Width="200" 34 Height="35" 35 Command="{Binding AddCmd}"/> 36 <DataGrid pu:DataGridHelper.SelectedItems="{Binding DataItems}"/> 37 </StackPanel> 38 </Grid> 39 </Window>