2012-02-28 17 views
7

Próbuję pobrać informacje o wierszu z datagridu po zdarzeniu z podwójnym kliknięciem. Mam konfigurację zdarzeń, ale teraz wystarczy ustawić funkcję, aby pobrać dane z wiersza.Uzyskiwanie informacji o wierszu po dwukliknięciu

XAML:

<DataGrid 
     Width="Auto" 
     SelectionMode="Extended" 
     IsReadOnly="True" 
     Name="ListDataGrid" 
     AutoGenerateColumns="False" 
     ItemsSource="{Binding ListFieldObject.MoviesList}" 
     DataContext="{StaticResource MovieAppViewModel}" 
     cal:Message.Attach="[Event MouseDoubleClick] = [Action RowSelect()]"> 

     <DataGrid.Columns> 
      <DataGridTextColumn Width="200" IsReadOnly="True" Header="Title" Binding="{Binding Title}"/> 
      <DataGridTextColumn Width="100" IsReadOnly="True" Header="Rating" Binding="{Binding Rating}"/> 
      <DataGridTextColumn Width="100" IsReadOnly="True" Header="Stars" Binding="{Binding Stars}"/> 
      <DataGridTextColumn Width="93" IsReadOnly="True" Header="Release Year" Binding="{Binding ReleaseYear}"/> 
     </DataGrid.Columns> 
    </DataGrid> 

C# (MVVM ViewModel):

 public void RowSelect() 
    { 
     //now how to access the selected row after the double click event? 
    } 

Dzięki dużo!

+0

Z tego co mogę powiedzieć, to jest bardzo trudne, jeśli nie niemożliwe. Opisuje to wiele stron internetowych, np. http://www.scottlogic.co.uk/blog/colin/2008/12/wpf-datagrid-detecting-clicked-cell-and-row/i to http://stackoverflow.com/questions/5808616/how-to-bind-a-command-to- dwukrotne kliknięcie-w-wierszu-w-datagrid – Phil

Odpowiedz

6

Z Caliburn to jest bardzo proste, wystarczy przekazać $ DataContext na XAML:

cal:Message.Attach="[Event MouseDoubleClick] = [Action RowSelect($dataContext)]"> 

i zmienić swoje metody:

public void RowSelect(MoviesListItem movie) 
{ 
    //now how to access the selected row after the double click event? 
} 

// EDIT Niestety, powyższe rozwiązanie będzie działać tylko wtedy, gdy działanie jest na samej DataTemplate ... Innym rozwiązaniem byłoby mieć powiązania SelectedItem i wystarczy użyć go na swojej metody:

<DataGrid 
    SelectedItem="{Binding SelectedMovie,Mode=TwoWay}" 
    cal:Message.Attach="[Event MouseDoubleClick] = [Action RowSelect()]"> 

i na kodzie:

public void RowSelect() 
{ 
    //SelectedMovie is the item where the user double-cliked 
} 
+0

Tak właśnie to zrobiłem. Dzięki za pomoc! – Josh

+0

To rozwiązanie jest opłacalne, ale z doświadczenia wynika, że ​​ma on nieprzewidywalne zachowanie, jeśli użytkownik szybko kliknie obszary siatki danych. Najbardziej znaczący przykład: użytkownik lubi szybko klikać strzałkę w dół lub kciuk na pionowym pasku przewijania, jeśli przewija dużą listę. Wielu użytkowników nie klika i nie przeciąga kciukiem, aby przewinąć; zamiast tego uderzają w strzałkę lub kciuk. To rozwiązanie niezmiennie spowoduje podwójne kliknięcie, ponieważ jest obsługiwane przez siatkę danych, a nie przez wiersz danych. – Adrian

+0

@Josh, to rozwiązanie będzie obsługiwać podwójne kliknięcia nagłówków kolumn, które prawie nie są konieczne. Aby temu zapobiec, należy rozważyć rozwiązanie z * David Kiff * poniżej. – Sevenate

1

(mam nadzieję, że to pomoże) nie jestem pewien swojej sprawy, ale to, co robię w WinForms:

  int index = dataGridView2.CurrentRow.Index; //determine which item is selected 
      textBox8.Text = dataGridView2.Rows[index].Cells[0].Value.ToString(); //add login 
+0

twoje wejście jest doceniane, ale używam wzorca MVVM i nie mogę mieć wywołań w kodzie z tyłu. Będę edytować oryginalny post, aby odzwierciedlić fakt, że C# jest w ViewModel. – Josh

1

Można to zrobić, modyfikując szablon kontrolny dla obiektu DataGridRows narażonego przez DataGrid. Poniższy przykład używa WPF i motywu Aero.

Jedyne, co zrobiłem, to usunięcie poprzedniego kalendarza: Message.Attach call i przeniesienie go do nowego "placeholder" ContentControl, który otacza Border (x: Name = DGR_Border) w "domyślnym" szablonie kontrolnym. (Użyłem ContentControl ponieważ ma swoje własne wizualizacje i naraża zdarzenie MouseDoubleClick.)

<DataGrid Width="Auto" 
      SelectionMode="Extended" 
      IsReadOnly="True" 
      Name="ListDataGrid" 
      AutoGenerateColumns="False" 
      ItemsSource="{Binding ListFieldObject.MoviesList}" 
      DataContext="{StaticResource MovieAppViewModel}"> 

    <DataGrid.Columns> 
     <DataGridTextColumn Width="200" IsReadOnly="True" Header="Title" Binding="{Binding Title}"/> 
     <DataGridTextColumn Width="100" IsReadOnly="True" Header="Rating" Binding="{Binding Rating}"/> 
     <DataGridTextColumn Width="100" IsReadOnly="True" Header="Stars" Binding="{Binding Stars}"/> 
     <DataGridTextColumn Width="93" IsReadOnly="True" Header="Release Year" Binding="{Binding ReleaseYear}"/> 
    </DataGrid.Columns> 
    <DataGrid.RowStyle> 
     <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/> 
     <Setter Property="SnapsToDevicePixels" Value="true"/> 
     <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/> 
     <Setter Property="ValidationErrorTemplate"> 
      <Setter.Value> 
       <ControlTemplate> 
        <TextBlock Foreground="Red" Margin="2,0,0,0" Text="!" VerticalAlignment="Center"/> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
     <Setter Property="Template"> 
      <Setter.Value>          
       <ControlTemplate TargetType="{x:Type DataGridRow}"> 
        <ContentControl cal:Message.Attach="[Event MouseDoubleClick] = [Action RowSelect($datacontext)]"> 
         <Border x:Name="DGR_Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> 
          <SelectiveScrollingGrid> 
           <SelectiveScrollingGrid.ColumnDefinitions> 
            <ColumnDefinition Width="Auto"/> 
            <ColumnDefinition Width="*"/> 
           </SelectiveScrollingGrid.ColumnDefinitions> 
           <SelectiveScrollingGrid.RowDefinitions> 
            <RowDefinition Height="*"/> 
            <RowDefinition Height="Auto"/> 
           </SelectiveScrollingGrid.RowDefinitions> 
           <DataGridCellsPresenter Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
           <DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Visibility="{TemplateBinding DetailsVisibility}"/> 
           <DataGridRowHeader Grid.RowSpan="2" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/> 
          </SelectiveScrollingGrid> 
         </Border> 
        </ContentControl> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </DataGrid.RowStyle> 
</DataGrid> 

Jedyne co musisz zrobić, to zmodyfikować metodę swój RowSelect(), aby zaakceptować parametr cokolwiek wpisz tutaj (założyłem, że był to typ "filmu").

public void RowSelect(Movie movie) 
{ 
    // do something with 'movie' 
} 
0

Mój przykład jest kolumna z NAZWĄ "service_id". Ale możesz również użyć przesunięcia kolumny int32. Istnieje nawet ItemArray w TYP DataRowView, aby uruchomić i zmniejszyć. Zobacz obszar nazw System.Data. Twoje zasoby/kontekst przedmiotu Datagrid będą miały wpływ na "obiekty" widoczne w Datagrid. Ale jeśli sprawdzisz debugowanie typów, możesz je przesyłać i używać.

private void DataGridServiceRegistry_MouseDoubleClick(object sender, MouseButtonEventArgs e) 
{ 
    DataGrid DGSR = (DataGrid) sender; 
    var SR = (DataRowView) DGSR.CurrentItem; 
    var service_id = SR.Row["SERVICE_ID"]; 
} 
17

Można alternatywnie to zrobić:

<DataGrid> 
    <DataGrid.RowStyle> 
     <Style TargetType="DataGridRow"> 
      <Setter Property="cal:Message.Attach" Value="[MouseDoubleClick] = [Action RowSelect($dataContext)]"/> 
     </Style> 
    </DataGrid.RowStyle> 
</DataGrid> 

Następnie

public void RowSelect(MoviesListItem movie) 
{ 
    //now how to access the selected row after the double click event? 
} 
+2

To znacznie lepsze rozwiązanie niż zaakceptowana odpowiedź, ponieważ przechwytuje tylko podwójne kliknięcia wierszy, ale nie nagłówków. – Sevenate

+1

Oto odpowiedź, której szukałem i która powinna być oznaczona jako odpowiedź. –

Powiązane problemy