1

I have a DataTrigger defined in a CellTemplate for a row in a ListViewItem inside a ListView ...how do I get it to select the entire row it is part of?

H.B.
  • 166,899
  • 29
  • 327
  • 400
blue18hutthutt
  • 3,191
  • 5
  • 34
  • 57
  • I think you should be looking at ListView.SelectedItem to set row selection. If you want to set the selection based on contents of your data, you should look at implementing an IsSelected property on your data rows, like this: http://stackoverflow.com/questions/803216/managing-multiple-selections-with-mvvm – Stafford Williams Aug 22 '12 at 07:20

2 Answers2

2

You shouldn't select a row in DataTrigger. Select it in your view model instead:

a) Define IsSelected property and change this property value, when condition, which DataTrigger is based on, becomes true:

public class DiabloIICharacter : ViewModelBase
{
    public String Name
    {
        get { return name; }
        set
        {
            if (name != value)
            {
                name = value;
                OnPropertyChanged("Name");
            }
        }
    }
    private String name;

    public Boolean IsBoss
    {
        get { return isBoss; }
        set
        {
            if (isBoss != value)
            {
                isBoss = value;
                OnPropertyChanged("IsBoss");

                if (isBoss)
                    // when a character becomes a boss, it becomes selected too
                    IsSelected = true;
            }
        }
    }
    private Boolean isBoss;

    public Boolean IsSelected
    {
        get { return isSelected; }
        set
        {
            if (isSelected != value)
            {
                isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }
    }
    private Boolean isSelected;
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new[]
        {
            new DiabloIICharacter { Name = "Diablo", IsBoss = true },
            new DiabloIICharacter { Name = "Oblivion Knight", IsBoss = false },
            new DiabloIICharacter { Name = "Blood Lord", IsBoss = false },
            new DiabloIICharacter { Name = "Andariel", IsBoss = true },
            new DiabloIICharacter { Name = "Baal", IsBoss = true },
            new DiabloIICharacter { Name = "Minion of Destruction", IsBoss = false },
            new DiabloIICharacter { Name = "Megademon", IsBoss = false },
        };
    }
}

b) Bind ListViewItem.IsSelected and ViewModel.IsSelected via ItemContainerStyle:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" 
        SizeToContent="WidthAndHeight">
    <Grid>
        <ListView ItemsSource="{Binding}">
            <ListView.Resources>
                <DataTemplate x:Key="IsBossTemplate">
                    <Rectangle Fill="Red" Width="50" Height="20" x:Name="IsBossMark"/>
                    <DataTemplate.Triggers>
                        <DataTrigger Value="True" Binding="{Binding IsBoss}">
                            <Setter TargetName="IsBossMark" Property="Fill" Value="DarkRed"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ListView.Resources>
            <ListView.ItemContainerStyle>
                <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Character name"
                                    DisplayMemberBinding="{Binding Name}"/>
                    <GridViewColumn Header="Is boss" 
                                    CellTemplate="{StaticResource IsBossTemplate}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>
Dennis
  • 37,026
  • 10
  • 82
  • 150
  • Funnily enough, that's what I ended up doing - felt a little hack-ish at the time but I'm starting to see that this is actually the normal / recommended way to do it in WPF / MVVM from examples I'm seeing of similar problems – blue18hutthutt Aug 22 '12 at 08:07
  • @blue18hutthutt: yes, it's true MVVM way. :) View model is a data, prepared to be displayed in the view. It is not a pure data. – Dennis Aug 22 '12 at 08:14
1

Just apply a Name to the ListView. like <ListView Name="mylistView"... /> now you can just create a binding in your celltemplate like this {Binding SelectedItem, ElementName=mylistView} and you have your binding to the selecteditem

Florian
  • 5,918
  • 3
  • 47
  • 86