WPF Datagrid循环/选择具有特定属性的单元格 [英] WPF Datagrid Cycle Through/Select Cells With Specific Property

查看:147
本文介绍了WPF Datagrid循环/选择具有特定属性的单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

全新的WPF,对WinForms非常舒适(这可能使得转换变得更加粗糙)。我正在尝试将一些旧的WinForms项目的功能移植到WPF中,作为学习体验。



目标是在与TextBox中的字符串匹配的DataGrid中查找单元格值。我发现使用将会执行的绑定的很棒的例子正是这样基本上,链接的代码将任何匹配的DataGridCell的背景颜色更改为橙​​色。我修改了我的版本,但功能应该是一样的。请参阅代码示例的链接,似乎在这里提供它有点多余。填充我的DataGrid的数据是一个来自DataTable(如果重要)。



我想要做的是有一个下一个按钮,它将循环遍历每个单元格(由使用背景颜色或自定义属性DataGridTextSearch确定) .IsTextMatch)并选择它。似乎有可能只是修改提供的代码一些,但我不知道从哪里开始。在我的旧WinForms项目中,我将DataGridViewCell存储在列表中(在使用Linq查询查找它们之后),并附加按钮行为来增加所述列表并设置当前单元格。我怀疑有可能是一个更聪明或更好的方式涉及到绑定,我甚至不知道如何添加这些匹配的单元格到一个列表,如果这是一个选项。因此,总而言之,我想要一个循环访问特定DataGridCells的按钮(基于背景或自定义DataGridTextSearch.IsTextMatch属性)并选择它们。



提前感谢。

解决方案

根据链接你在你的问题中提供了一个解决方案。在我的解决方案中,当 DataGridCell 匹配 TextBox 中的字符串时,它的标签属性将被设置为1,然后当 Button 被点击时,它将遍历所有 DataGridCells 并找到非空值标签的项目,最后突出显示的单元格将逐个聚焦。



以下是一个工作示例,给您一个想法:



Xaml:

 < Window Name =UI> 
< Grid>
< Grid.RowDefinitions>
< RowDefinition Height =*/>
< RowDefinition Height =Auto/>
< /Grid.RowDefinitions>
< StackPanel DataContext ={Binding ElementName = UI}Grid.Row =0>
< TextBox Name =SearchBoxTextChanged =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.IsTextMatchValue =True>
< Setter Property =BackgroundValue =Orange/>
< Setter Property =TagValue =1/>
< / Trigger>
< /Style.Triggers>
< / Style>
< /DataGrid.Resources>
< / DataGrid>
< / StackPanel>
< Button Grid.Row =1Click =Button_ClickContent =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 ++;
}

获取突出显示的单元格的方法:

  public List< DataGridCell> GetHighLightedCells()
{
列表< DataGridCell> selectedCells = new List< DataGridCell>();
foreach(GetDataGridRows()中的DataGridRow rowContainer)
{
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(itemSource中的var item)
{
var row = grid.ItemContainerGenerator.ContainerFromItem(item)as DataGridRow;
if(null!= row)yield return row;
}
}

public static T GetVisualChild< T>(Visual parent)其中T:Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent); (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;
}


Brand new to WPF, pretty comfortable with WinForms (which is probably making the transition rougher). I'm trying to port some functionality from an old WinForms project into WPF as a learning experience.

The goal is to find cell values in a DataGrid matching a string in a TextBox. I found a great example using bindings that will do exactly that. Basically the linked code will change the background color of any matching DataGridCell to orange. I've modified my version a bit, but the functionality should be the same. Please see the link for code examples, seems a bit redundant to provide it here. The data populating my DataGrid is a from a DataTable (if that matters).

What I want to do from there is have a "next" button that will cycle through each of those cells (determined by either using the background color or the custom property DataGridTextSearch.IsTextMatch) and select it. Seems like it would be possible to just modify the provided code some, but I don't know where to begin. In my old WinForms project I stored the DataGridViewCell in a list (after finding them with a Linq query) and just attached the button behavior to incrementing said list and setting the current cell. I suspect there's probably a smarter/better way involving bindings, and I don't even know how to add these matching cells to a list if that were an option.

So, to summarize, I want a button that cycles through specific DataGridCells (based on the Background or the custom DataGridTextSearch.IsTextMatch property) and selects them.

Thanks in advance.

解决方案

Based on the link you provided in your question, I've come to a solution for this. In my solution when a DataGridCell matches the string in the TextBox, it's Tag property will be set to "1" and then when the Button gets clicked, it'll iterate through all DataGridCells and find items with non-null Tags and finally highlighted cells will be focused one by one.

Here is a working example to give you an idea:

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++;
}

Methods to get highlighted cells:

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;
}

这篇关于WPF Datagrid循环/选择具有特定属性的单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆