SelectedItems如何Binding

在WPF中,不论是ListBox,ListView或者DataGrid,在使用中都会经常用到SelectedItems,但是在Xaml中却发现SelectedItems没有办法Binding。这是因为SelectedItems是一个只读属性,且不是一个DependencyProperty,所以没法Binding。不过我们却可以通过以下几种方法来实现这个功能:

【方案一】

使用后台代码,读取这个控件的SelectedItems属性。例如
XAML:

1
2
<ListView  ItemsSource="{Binding}" x:Name="lvTest">
</ListView>

那么后台就可以

1
2
3
4
foreach(XX item in lvTest.SelectedItems)
{
//Operation
}

如果列表控件是作为ControlTemplate的内容,那么就在后台获取ControlTemplate下的这个控件

1
var lvTest= XX.Template.FindName("lvTest", XX);

【方案二】

可以通过修改SelectionChanged事件来通知后台该控件选择的项。MSDN中提供了这一解决方案。

XAML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<Window x:Class="ListViewSelectedItemsBinding.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:local="clr-namespace:ListViewSelectedItemsBinding"

xmlns:w="clr-namespace:System.Windows.Workarounds"

x:Name="root" Width="500" Height="700">

<Window.Resources>

<local:MyConverter x:Key="myConverter"/>

</Window.Resources>

<StackPanel>

<ListView x:Name="listView" ItemsSource="{Binding}" SelectionMode="Extended"

SelectionChanged="listView_SelectionChanged"

w:ListView.HasBindableSelectedItems="True">

<ListView.View>

<GridView>

<GridViewColumn Header="Artist" DisplayMemberBinding="{Binding Path=Artist}" />

<GridViewColumn Header="Title" DisplayMemberBinding="{Binding Path=Title}" />

<GridViewColumn Header="Genre" DisplayMemberBinding="{Binding Path=Genre}" />

</GridView>

</ListView.View>

</ListView>

<StackPanel Background="LightGreen">

<DockPanel>

<Label DockPanel.Dock="Left" Content="SelectedItems.Count = " />

<TextBox Text="{Binding ElementName=listView, Path=SelectedItems.Count, Mode=OneWay}" IsReadOnly="True" />

</DockPanel>

<DockPanel>

<Label DockPanel.Dock="Left" Content="SelectedItems = " />

<TextBox Text="{Binding ElementName=listView, Path=SelectedItems, Mode=OneWay,

Converter={StaticResource myConverter}, ConverterParameter='Artist'}" IsReadOnly="True" />

</DockPanel>

</StackPanel>

<StackPanel Background="LightBlue">

<DockPanel>

<Label DockPanel.Dock="Left" Content="Selection.Count = " />

<TextBox Text="{Binding ElementName=root, Path=Selection.Count, Mode=OneWay}" IsReadOnly="True" />

</DockPanel>

<DockPanel>

<Label DockPanel.Dock="Left" Content="Selection = " />

<TextBox Text="{Binding ElementName=root, Path=Selection, Mode=OneWay,

Converter={StaticResource myConverter}, ConverterParameter='Artist'}" IsReadOnly="True" />

</DockPanel>

</StackPanel>

<local:PropertiesPanel x:Name="propertiesPanel1" Background="LightGreen"

Subjects="{Binding ElementName=listView, Path=SelectedItems, Mode=OneWay}" />

<local:PropertiesPanel x:Name="propertiesPanel2" Background="LightBlue"

Subjects="{Binding ElementName=root, Path=Selection, Mode=OneWay}" />

<local:PropertiesPanel x:Name="propertiesPanel3" Background="LightPink"

Subjects="{Binding ElementName=listView, Path=BindableSelectedItems}" />

</StackPanel>

</Window>

后台

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
using System;
using System.Collections;
using System.Windows.Data;
using System.Windows.Controls;
namespace System.Windows.Workarounds
{
public static class ListView

{

public static readonly DependencyProperty HasBindableSelectedItemsProperty;

public static readonly DependencyProperty BindableSelectedItemsProperty;

static DependencyProperty SelectionChangedHandlerProperty;



static ListView()

{

BindableSelectedItemsProperty = DependencyProperty.Register("BindableSelectedItems", typeof(IList), typeof(System.Windows.Controls.ListView));

HasBindableSelectedItemsProperty = DependencyProperty.RegisterAttached("HasBindableSelectedItems", typeof(bool), typeof(System.Windows.Controls.ListView), new PropertyMetadata(false));

SelectionChangedHandlerProperty = DependencyProperty.RegisterAttached("SelectionChangedHandler", typeof(SelectionChangedHandler), typeof(System.Windows.Controls.ListView));

}



public static void SetHasBindableSelectedItems(System.Windows.Controls.ListView source, bool value)
{
SelectionChangedHandler Handler = (SelectionChangedHandler)source.GetValue(SelectionChangedHandlerProperty);

if (value && Handler == null)
{
Handler = new SelectionChangedHandler(source);
source.SetValue(SelectionChangedHandlerProperty, Handler);
}
else if (!value && Handler != null)
{
source.ClearValue(SelectionChangedHandlerProperty);
}
}

}



internal class SelectionChangedHandler
{

Binding Binding;
internal SelectionChangedHandler(System.Windows.Controls.ListView owner)
{
Binding = new Binding("SelectedItems");
Binding.Source = owner;
owner.SetBinding(ListView.BindableSelectedItemsProperty, Binding);
owner.SelectionChanged += new SelectionChangedEventHandler(Owner_SelectionChanged);
}

void Owner_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
System.Windows.Controls.ListView Owner = (System.Windows.Controls.ListView)sender;
BindingOperations.ClearBinding(Owner, ListView.BindableSelectedItemsProperty);
Owner.SetBinding(ListView.BindableSelectedItemsProperty, Binding);
}
}
}

【方案三】

可以重写SelectedItems实现Binding,方案可以参考这里

作者

Wu Rang

发布于

2014-03-07

更新于

2021-12-06

许可协议

评论