it-swarm.com.de

WPF ListView: Hinzufügen eines Doppelklicks (auf ein Element)

Ich habe folgende ListView:

<ListView Name="TrackListView">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Title" Width="100" 
                            HeaderTemplate="{StaticResource BlueHeader}" 
                            DisplayMemberBinding="{Binding Name}"/>

            <GridViewColumn Header="Artist" Width="100"  
                            HeaderTemplate="{StaticResource BlueHeader}"  
                            DisplayMemberBinding="{Binding Album.Artist.Name}" />
        </GridView>
    </ListView.View>
</ListView>

Wie kann ich ein Ereignis an jedes gebundene Objekt anhängen, das beim Doppelklicken auf das Objekt ausgelöst wird?

78
Andreas Grech

Hier finden Sie die Lösung: http://social.msdn.Microsoft.com/Forums/de/wpf/thread/3d0eaa54-09a9-4c51-8677-8e90577e7bac/


XAML:

<UserControl.Resources>
    <Style x:Key="itemstyle" TargetType="{x:Type ListViewItem}">
        <EventSetter Event="MouseDoubleClick" Handler="HandleDoubleClick" />
    </Style>
</UserControl.Resources>

<ListView Name="TrackListView" ItemContainerStyle="{StaticResource itemstyle}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Title" Width="100" HeaderTemplate="{StaticResource BlueHeader}" DisplayMemberBinding="{Binding Name}"/>
            <GridViewColumn Header="Artist" Width="100" HeaderTemplate="{StaticResource BlueHeader}" DisplayMemberBinding="{Binding Album.Artist.Name}" />
        </GridView>
    </ListView.View>
</ListView>

C #:

protected void HandleDoubleClick(object sender, MouseButtonEventArgs e)
{
    var track = ((ListViewItem) sender).Content as Track; //Casting back to the binded Track
}
94
Andreas Grech

Kein Speicherleck, funktioniert gut:

XAML:

<ListView ItemsSource="{Binding TrackCollection}" MouseDoubleClick="ListView_MouseDoubleClick" />

C #:

    void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        var item = ((FrameworkElement) e.OriginalSource).DataContext as Track;
        if (item != null)
        {
            MessageBox.Show("Item's Double Click handled!");
        }
    }
60
epox_spb

Meine Lösung basierte auf @ epox_subs Antwort , auf die Sie achten sollten, wo der Event Handler in der XAML abgelegt wird. Der Code-Behind hat für mich nicht funktioniert, da meine ListViewItems komplexe Objekte sind. @sipwiz's answer war ein toller Hinweis, wo man suchen muss ...

void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    var item = ListView.SelectedItem as Track;
    if (item != null)
    {
      MessageBox.Show(item.ToString()+" Double Click handled!");
    }
}

Der Bonus dabei ist, dass Sie die DataContext-Bindung der SelectedItem (in diesem Fall Track) erhalten. Das ausgewählte Element funktioniert, weil der erste Klick des Doppelklicks es auswählt.

5
CAD bloke

Für diejenigen, die am MVVM-Muster interessiert sind, habe ich die Antwort von Andreas Grech verwendet, um eine Lösung zu finden.

Grundablauf:

Der Benutzer klickt doppelt auf Element -> Ereignishandler im Code hinter -> ICommand in Modell anzeigen

ProjectView.xaml:

<UserControl.Resources>
    <Style TargetType="ListViewItem" x:Key="listViewDoubleClick">
        <EventSetter Event="MouseDoubleClick" Handler="ListViewItem_MouseDoubleClick"/>
    </Style>
</UserControl.Resources>

...

<ListView ItemsSource="{Binding Projects}" 
          ItemContainerStyle="{StaticResource listViewDoubleClick}"/>

ProjectView.xaml.cs:

public partial class ProjectView : UserControl
{
    public ProjectView()
    {
        InitializeComponent();
    }

    private void ListViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        ((ProjectViewModel)DataContext)
            .ProjectClick.Execute(((ListViewItem)sender).Content);
    }
}

ProjectViewModel.cs:

public class ProjectViewModel
{
    public ObservableCollection<Project> Projects { get; set; } = 
               new ObservableCollection<Project>();

    public ProjectViewModel()
    {
        //Add items to Projects
    }

    public ICommand ProjectClick
    {
        get { return new DelegateCommand(new Action<object>(OpenProjectInfo)); }
    }

    private void OpenProjectInfo(object _project)
    {
        ProjectDetailView project = new ProjectDetailView((Project)_project);
        project.ShowDialog();
    }
}

DelegateCommand.cs kann nach hier gefunden werden.

In meiner Instanz habe ich eine Sammlung von Project-Objekten, die die ListView ausfüllen. Diese Objekte enthalten mehr Eigenschaften, als in der Liste angezeigt werden, und ich öffne eine ProjectDetailView (eine WPF Window), um sie anzuzeigen.

Das sender-Objekt des Event-Handlers ist die ausgewählte ListViewItem. Anschließend ist die Project, auf die ich zugreifen möchte, in der Content-Eigenschaft enthalten.

3
Micah Vertal

Versuchen Sie in Ihrem Beispiel zu fangen, wenn ein Element in Ihrer ListView ausgewählt wird oder wenn auf eine Spaltenüberschrift geklickt wird. Wenn es sich um den ersteren handelt, würden Sie einen SelectionChanged-Handler hinzufügen.

<ListView Name="TrackListView" SelectionChanged="MySelectionChanged">

In letzterem Fall müssten Sie eine Kombination aus MouseLeftButtonUp- oder MouseLeftButtonDown-Ereignissen für die GridViewColumn-Elemente verwenden, um einen Doppelklick zu erkennen und entsprechende Maßnahmen zu ergreifen. Alternativ können Sie die Ereignisse in der GridView behandeln und von dort aus ermitteln, welche Spaltenüberschrift sich unter der Maus befand.

3
sipwiz

Aufbauend auf epox_spbs Antwort habe ich eine Überprüfung hinzugefügt, um Fehler beim Doppelklicken in den GridViewColumn-Headern zu vermeiden.

void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    var dataContext = ((FrameworkElement)e.OriginalSource).DataContext;
    if (dataContext is Track)
    {
        MessageBox.Show("Item's Double Click handled!");
    }
}
0
Kramer