Silverlight 5 ListBox IsSelected 样式绑定(bind)坏了?

标签 silverlight mvvm binding

我看到 Silverlight 5 购买了样式绑定(bind)。试图将它应用到 ListBox 控件中,以进行多选。我有以下 XAML ListBox(代码在 WPF 应用程序中工作)。

     <ListBox ItemsSource="{Binding Values}" SelectionMode="Multiple">
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate DataType="ListBoxItem">
                <TextBlock Text="{Binding DisplayValue}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

当我运行它时,我得到一个绑定(bind)错误,它似乎试图在“值”集合的类型上查找 IsSelected 属性,而不是该集合中的每个单独项目。有没有其他人经历过这个?

更新
添加完整代码重现,需要滚动列表框才能看到输出日志中的错误
public class ValueViewModel : INotifyPropertyChanged
{
    private bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set
        {
            _isSelected = value;
            OnPropertyChanged("IsSelected");
        }
    }

    private string _displayValue;
    public string DisplayValue
    {
        get { return _displayValue; }
        set
        {
            _displayValue = value;
            OnPropertyChanged("DisplayValue");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class MainPageViewModel : INotifyPropertyChanged
{

    public ObservableCollection<ValueViewModel> _values;
    public ObservableCollection<ValueViewModel> Values
    {
        get { return _values; }
        set
        {
            _values = value;
            OnPropertyChanged("Values");
        }
    }

    public MainPageViewModel()
    {
        Values = new ObservableCollection<ValueViewModel>();

        for (var i = 0; i < 50; i++)
            Values.Add(new ValueViewModel() { DisplayValue = i.ToString(), IsSelected = (i % 5) == 0 });
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

和 XAML:

<Grid x:Name="LayoutRoot" Background="White" >
    <Grid.Resources>
        <viewmodels:MainPageViewModel x:Key="vmMainPage"/>
    </Grid.Resources>
    <Grid x:Name="workGrid" DataContext="{Binding Source={StaticResource vmMainPage}}">
        <ListBox ItemsSource="{Binding Values}" SelectionMode="Multiple" Height="100">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Margin="5" Text="{Binding DisplayValue}"/>
                        <TextBlock Margin="5" Text="{Binding IsSelected}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Grid>

更新 2
似乎围绕错误的问题是,在可滚动的情况下,如果您选择项目 1,然后向下滚动并选择项目 49(在上面的示例中),则第一个选择会丢失。

最佳答案

我无法重现它。这对我来说可以。这是基于您的代码的完整工作示例。不过,我确实注意到的一个问题是,当呈现 ListBoxItem 时,它会自动将数据对象上的属性设置为 false,而不管它一开始是否为 true。因此,如果您加载一个列表并将其中的一些项目设置为预选,则在呈现 ListBoxItems 时,所有项目都将被取消选择。防止这种情况的一种方法是使用 Dispatcher.BeginInvoke 并在那里设置所选项目。在下面的代码中查看我的评论。

XAML:

<UserControl x:Class="SilverlightApplication12.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             d:DesignHeight="300"
             d:DesignWidth="400">

    <Grid x:Name="LayoutRoot"
          Background="White">

        <ListBox ItemsSource="{Binding Entities}"
                 SelectionMode="Multiple">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="IsSelected"
                            Value="{Binding Path=IsSelected, Mode=TwoWay}" />
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBox.ItemTemplate>
                <DataTemplate DataType="ListBoxItem">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name}" />
                        <TextBlock Margin="10 0 0 0"
                                   Text="IsSelected:" />
                        <TextBlock Margin="5 0 0 0"
                                   Text="{Binding IsSelected}"></TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

    </Grid>
</UserControl>

代码隐藏+实体类:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightApplication12
{
    public partial class MainPage : UserControl, INotifyPropertyChanged
    {
        private ObservableCollection<MyEntity> _Entities;

        public ObservableCollection<MyEntity> Entities
        {
            get { return _Entities; }
            set
            {
                _Entities = value;
                OnPropertyChanged("Entities");
            }
        }

        public MainPage()
        {
            InitializeComponent();

            Entities = new ObservableCollection<MyEntity>();
            Entities.Add(new MyEntity()
            {
                Name = "One",
                IsSelected = false,
            });
            Entities.Add(new MyEntity()
            {
                Name = "Two",
                IsSelected = true,
                //Even though this is initially true it does not matter. 
                //When the ListBoxItem is rendered it sets the property to false. 
            });
            Entities.Add(new MyEntity()
            {
                Name = "Three",
                IsSelected = false,
            });

            LayoutRoot.DataContext = this;

            //Enable the following line to set the 2nd item to selected when the page is loaded. 
            //Dispatcher.BeginInvoke(() => Entities[1].IsSelected = true);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    public class MyEntity : INotifyPropertyChanged
    {
        private string _Name;

        public string Name
        {
            get { return _Name; }
            set
            {
                _Name = value;
                OnPropertyChanged("Name");
            }
        }

        private bool _IsSelected;

        public bool IsSelected
        {
            get
            {
                return _IsSelected;
            }
            set
            {
                _IsSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

关于Silverlight 5 ListBox IsSelected 样式绑定(bind)坏了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15655489/

相关文章:

Silverlight 2如何知道所有ASYNC WCF调用已经完成

c# - 将窗口关闭事件绑定(bind)到 ICommand

asp.net-mvc - 我应该在我的服务`DTO 还是客户端 ViewModel 中定义 UI 默认值

c# - WPF FontFamily格式问题

c# - WPF:将 ItemsSource 绑定(bind)到目录

silverlight - 迁移 Silverlight 应用程序的指南

html - 如何从同一页面上现有 silverlight 容器的超链接打开 url

wpf - Silverlight按钮样式如何在按下按钮时防止其处于聚焦状态?

c# - 使用 MVVM-Light 这是引发事件的正确方法吗?坚持到底应该去哪里?

c - 使用 tolua++ 绑定(bind)结构和 ctor/dtor