2015-10-13 15 views
5

Fabrycznie nowe dla WPF, całkiem wygodne z WinForms (co prawdopodobnie powoduje, że przejście staje się trudniejsze). Próbuję przenieść niektóre funkcjonalności ze starego projektu WinForms do WPF w celu uczenia się.WPF Datagrid Cycle Through/Select Komórki o określonej właściwości

Celem jest znalezienie wartości komórki w DataGrid pasującej do napisu w TextBox. Znalazłem great example za pomocą wiązań, które zrobią dokładnie to. Zasadniczo połączony kod zmieni kolor tła dowolnego pasującego elementu DataGridCell na pomarańczowy. Trochę zmodyfikowałem swoją wersję, ale funkcjonalność powinna być taka sama. Zobacz link do przykładów kodu, wydaje się nieco zbędny, aby podać go tutaj. Dane wypełniające moją kartę DataGrid pochodzą z DataTable (jeśli to ma znaczenie).

To, co chcę zrobić, to mieć przycisk "następny", który przejdzie przez każdą z tych komórek (określaną za pomocą koloru tła lub niestandardowej właściwości DataGridTextSearch.IsTextMatch) i wybierz go. Wygląda na to, że można trochę zmodyfikować podany kod, ale nie wiem, od czego zacząć. W moim starym projekcie WinForms zapisałem DataGridViewCell na liście (po znalezieniu ich za pomocą zapytania Linq) i po prostu przywiązałem zachowanie przycisku do zwiększania tej listy i ustawiania bieżącej komórki. Podejrzewam, że prawdopodobnie istnieje lepszy/lepszy sposób obejmujący wiązania i nawet nie wiem, jak dodać te pasujące komórki do listy, jeśli taka opcja istnieje.

Podsumowując, chcę przycisku, który przechodzi przez określone komórki DataGridCells (na podstawie tła lub niestandardowej właściwości DataGridTextSearch.IsTextMatch) i wybiera je.

Z góry dziękuję.

Odpowiedz

5

Na podstawie podanego w pytaniu link, znalazłem rozwiązanie problemu. W moim rozwiązaniu, gdy DataGridCell pasuje do ciągu znaków w TextBox, właściwość Tag zostanie ustawiona na "1", a następnie kliknięcie przycisku Button spowoduje iterację wszystkich DataGridCells i znalezienie elementów o wartości innej niż zero Tags i ostatecznie podświetlonych komórek będzie skupiony jeden po drugim.

Oto przykład do pracy daje wyobrażenie:

XAML:

<Window Name="UI"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <StackPanel DataContext="{Binding ElementName=UI}" Grid.Row="0"> 
      <TextBox Name="SearchBox" TextChanged="SearchBox_TextChanged"/> 
      <DataGrid x:Name="grid" 
        m:DataGridTextSearch.SearchValue="{Binding ElementName=SearchBox, Path=Text, UpdateSourceTrigger=PropertyChanged}" 
        ItemsSource="{Binding TestData}" 
        SelectionUnit="Cell"> 
       <DataGrid.Resources> 
        <m:SearchValueConverter x:Key="SearchValueConverter" /> 
        <Style TargetType="{x:Type DataGridCell}"> 
         <Setter Property="m:DataGridTextSearch.IsTextMatch"> 
          <Setter.Value> 
           <MultiBinding Converter="{StaticResource SearchValueConverter}"> 
            <Binding RelativeSource="{RelativeSource Self}" Path="Content.Text" /> 
            <Binding RelativeSource="{RelativeSource Self}" Path="(m:DataGridTextSearch.SearchValue)" /> 
           </MultiBinding> 
          </Setter.Value> 
         </Setter> 
         <Style.Triggers> 
          <Trigger Property="m:DataGridTextSearch.IsTextMatch" Value="True"> 
           <Setter Property="Background" Value="Orange" /> 
           <Setter Property="Tag" Value="1" /> 
          </Trigger> 
         </Style.Triggers> 
        </Style> 
       </DataGrid.Resources> 
      </DataGrid> 
     </StackPanel> 
     <Button Grid.Row="1" Click="Button_Click" Content="GoNext"/> 
    </Grid> 
</Window> 

MainWindow.cs:

int currentIndex = 0; 

private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) 
{ 
    currentIndex = 0; 
} 

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    var selectedCells = GetHighLightedCells(); 
    if (selectedCells.Count == 0) 
     return; 

    selectedCells[currentIndex].Focus(); 

    if (currentIndex == selectedCells.Count - 1) 
     currentIndex = 0; 
    else 
     currentIndex++; 
} 

metod, aby uzyskać podświetloną komórki:

public List<DataGridCell> GetHighLightedCells() 
{ 
    List<DataGridCell> selectedCells = new List<DataGridCell>(); 
    foreach (DataGridRow rowContainer in GetDataGridRows()) 
    { 
     if (rowContainer != null) 
     { 
      DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer); 
      foreach (var col in grid.Columns) 
      { 
       DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(col.DisplayIndex); 
       if (cell == null) 
       { 
        grid.ScrollIntoView(rowContainer, col); 
        cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(col.DisplayIndex); 
       } 
       if (cell.Tag != null) 
       { 
        selectedCells.Add(cell); 
       } 
      } 
     } 
    } 
    return selectedCells; 
} 
public IEnumerable<DataGridRow> GetDataGridRows() 
{ 
    var itemsSource = grid.ItemsSource as IEnumerable; 
    if (null == itemsSource) yield return null; 
    foreach (var item in itemsSource) 
    { 
     var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow; 
     if (null != row) yield return row; 
    } 
} 

public static T GetVisualChild<T>(Visual parent) where T : Visual 
{ 
    T child = default(T); 
    int numVisuals = VisualTreeHelper.GetChildrenCount(parent); 
    for (int i = 0; i < numVisuals; i++) 
    { 
     Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); 
     child = v as T; 
     if (child == null) 
     { 
      child = GetVisualChild<T>(v); 
     } 
     if (child != null) 
     { 
      break; 
     } 
    } 
    return child; 
} 
+1

Niesamowite. Właściwie pracowałem nad czymś podobnym, ale na zawsze zajęłoby mi to całe rozwiązanie. Doceniam to! Dziękuję Ci. – Finch042

+0

Serdecznie zapraszamy :) –