1. 程式人生 > 其它 >WPF 使用附加屬性來繫結ListBox的SelectedItems

WPF 使用附加屬性來繫結ListBox的SelectedItems

 

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 { 19
public 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>