为什么我的WPF listview代码在以编程方式选择行时抛出异常

时间:2013-04-05 18:37:38

标签: c# wpf listview selection listviewitem

我正在尝试以编程方式突出显示WPF listview控件中的第一行,使用带有3.5 .NET框架的VS2008。这是C#代码:

ListViewItem Val = (ListViewItem)ListView1.Items[0];
Val.IsSelected = true;

代码在第一行引发异常,这是在ListView1填充数据之后。异常中的消息说:

“无法将'Message.LV1Data'类型的对象强制转换为'System.Windows.Controls.ListViewItem'。”

LV1Data是我用来绑定此控件中的列的类。因此,看起来它正在尝试返回LV1Data对象而不是ListViewItem对象。有没有人对我做错了什么或者我需要做什么来建议以编程方式突出显示列表视图行?

以下是ListView控件的XAML代码:

<ListView x:Name="ListView1" ItemContainerStyle="{StaticResource alternatingListViewItemStyle}" AlternationCount="2" SelectionChanged="ListView1_SelectionChanged"
 SelectionMode="Multiple" HorizontalAlignment="Left" ItemsSource = "{Binding ElementName=LobbyWindow, Path=ListCollection1}">
   <ListView.View>
      <GridView>
         <GridViewColumn DisplayMemberBinding="{Binding Game}">
         <GridViewColumnHeader Content="Game" FontWeight="Bold" />
         </GridViewColumn>
         <GridViewColumn DisplayMemberBinding="{Binding Stakes}">
         <GridViewColumnHeader Content="Stakes" Width="68" FontWeight="Bold" />
         </GridViewColumn>
         <GridViewColumn Width="30" DisplayMemberBinding="{Binding Seats}">
         <GridViewColumnHeader Content="Seats" FontWeight="Bold" />
         </GridViewColumn>
      </GridView>
   </ListView.View>
</ListView>

修改

<!-- Define the resource for the alternating background background used in the ListView objects.  -->
<StackPanel.Resources>
   <Style x:Key="alternatingListViewItemStyle" TargetType="{x:Type ListViewItem}">
      <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
      <Style.Resources>
         <!-- Foreground for Selected ListViewItem -->
         <!-- <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/> -->
         <!-- Background for Selected ListViewItem -->
         <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Green"/>
         <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Brown"/>
      </Style.Resources>
      <Style.Triggers>
         <!-- setting up triggers for alternate background colors -->
         <Trigger Property="ItemsControl.AlternationIndex" Value="1">
            <Setter Property="Background" Value="#FFD9F2BF"></Setter>
         </Trigger>
         <Trigger Property="ItemsControl.AlternationIndex" Value="2">
            <Setter Property="Background" Value="White"></Setter>
         </Trigger>
         <Trigger Property="IsSelected" Value="True">
            <Setter Property="Background" Value="LightBlue"></Setter>
         </Trigger>
         <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="BorderBrush" Value="LightBlue" />
         </Trigger>
         <MultiTrigger>
            <MultiTrigger.Conditions>
               <Condition Property="IsSelected" Value="True"></Condition>
               <Condition Property="ItemsControl.AlternationIndex" Value="0"></Condition>
            </MultiTrigger.Conditions>
            <Setter Property="Background" Value="LightBlue"></Setter>
         </MultiTrigger>
         <MultiTrigger>
            <MultiTrigger.Conditions>
               <Condition Property="IsSelected" Value="True"></Condition>
               <Condition Property="ItemsControl.AlternationIndex" Value="1"></Condition>
            </MultiTrigger.Conditions>
            <Setter Property="Background" Value="LightGreen"></Setter>
         </MultiTrigger>
      </Style.Triggers>
      <!-- setting row height here -->
   </Style>
</StackPanel.Resources>

2 个答案:

答案 0 :(得分:2)

绑定到项目源,这意味着要求项目[x]将返回您绑定的数据类型(ListCollection1中存储的任何类型)。

如果要更改它的IsSelected,则必须在ListCollection1中的类型上创建该属性,并在样式或模板中绑定它。

您创建的IsSelected属性必须实现为DependencyProperty,或者它所在的Type必须实现INotifyPropertyChanged,并在属性更改时触发该事件。

<ListView ItemsSource="...">
   <ListView.ItemContainerStyle>
      <Style TargetType="{x:Type ListViewItem}">
         <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
      </Style>
   </ListView.ItemContainerStyle>
</ListView>

然后你将转换为该数据对象类型,并设置它的IsSelected值。

在代码中查找ListCollection1。它的定义看起来像List<Element>Element是您需要投射的类型。

元素需要看起来像

public class Element : INotifyPropertyChanged
{
   private _IsSelected;
   public Boolean IsSelected 
   { 
      get { return _IsSelected; }
      set 
      { 
          _IsSelected = value; 
          if (PropertyChanged != null) 
             PropertyChanged("IsSelected");
      }
   }    

   //snip Implement interface INotifyPropertyChanged.

   //snip your other code
}

-OR -

public class Element : DependencyObject
{
    public static DependencyProperty IsSelectedProperty =
       DependencyProperty.Register("IsSelected" ...

   //snip your other code
}

然后你的代码应该是这样的。

Element Val = (Element)ListView1.Items[0];
Val.IsSelected = true;

答案 1 :(得分:1)

项目绑定到您的业务对象,这就是为什么它实际上没有返回listview项目。你可以尝试三件事:

Use SetSelectedItems并且只传入一个对象的IEnumerable

或者,您可以获取该对象,然后询问它引用的ListViewItem

(ListViewItem)ListView1.ItemContainerGenerator.ContainerFromItem(ListView1.Items[0])

或者,您可以绑定到IsSelected属性并在viewmodel中管理它