目录

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,方案可以参考这里