Pergunta

Eu tenho esse conversor, ele leva:o DataGridCell atual, um objeto DataGridCellInfo e estou tentando colocar o objeto DataGrid lá também.

    <Style TargetType="{x:Type DataGridCell}" x:Key="cellStyle" >
        <Setter Property="helpers:SearchBehaviours.IsTextMatchFocused">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource SelectedSearchValueConverter}" FallbackValue="False">
                    <Binding RelativeSource="{x:Static RelativeSource.Self}"/>
                    <Binding Source="{x:Static helpers:MyClass.Instance}" Path="CurrentCellMatch" />
                    <Binding ElementName="GenericDataGrid"/>
                </MultiBinding>
            </Setter.Value>
        </Setter>
    </Style>

Tentei apenas vincular o DataGrid conforme abaixo, porém quando ele é virtualizado e você rola para baixo e os itens são reciclados, a ligação é descartada e gera um erro.

Aviso de sistema.Windows.Data:4:Não é possível encontrar a fonte para ligação com a referência 'ElementName = GenericDataGrid'.Expressão de Ligação:Caminho=;DataItem=nulo;o elemento de destino é 'DataGridCell' (Nome='');A propriedade de destino é 'IsTextMatchFocused' (Type 'Boolean')

No conversor abaixo, o DataGridCell é convertido em um DataGridCellInfo, e estou basicamente comparando os índices de linha e coluna dos dois DataGridCellInfo para ver se eles correspondem, em caso afirmativo, retorne verdadeiro.

Para fazer isso eu preciso do objeto DataGrid.Posso ver três soluções possíveis:
1.Talvez eu possa apenas comparar os dois objetos DataGridCellInfo para ver se eles são iguais, sem precisar usar um objeto DataGrid.(Eu tentei isso, mas sempre retorna falso)
2.Obtenha o DataGrid real de um dos objetos DataGridCellInfo, pois é pai.(Não sei como fazer isso).
3.Faça a ligação funcionar de uma maneira diferente.

Obviamente, este conversor será executado em várias células sempre que uma das ligações for alterada, então gostaria que fosse o mais eficiente possível.

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    try
    {
        if (values[0] == null || values[1] == null || values[2] == null)
        {
            return false;
        }

        DataGridCellInfo currentCellInfoMatch = (DataGridCellInfo)values[1];
        if (currentCellInfoMatch.Column == null)
            return false;

        DataGridCellInfo cellInfo = new DataGridCellInfo((DataGridCell)values[2]);
        if (cellInfo.Column == null)
            return false;

        DataGrid dg = (DataGrid)values[3];

        int cellInfoItemIndex = ((DataGridRow)dg.ItemContainerGenerator.ContainerFromItem(cellInfo.Item)).GetIndex();
        int cellInfoColumnIndex = cellInfo.Column.DisplayIndex;
        int currentCellInfoMatchItemIndex = ((DataGridRow)dg.ItemContainerGenerator.ContainerFromItem(currentCellInfoMatch.Item)).GetIndex();
        int currentCellInfoMatchColumnIndex = currentCellInfoMatch.Column.DisplayIndex;

        if (cellInfoItemIndex == currentCellInfoMatchItemIndex && cellInfoColumnIndex == currentCellInfoMatchColumnIndex)
            return true;

        return false;
    }
    catch (Exception ex)
    {
        Console.WriteLine("SelectedSearchValueConverter error : " + ex.Message);
        return false;
    }
}
Foi útil?

Solução

Embora eu goste da solução dada de fornecê-lo ao conversor por meio de um RelativeSource, isso também pode ser feito de uma maneira diferente.É possível não passar um parâmetro DataGrid, mas sim localizá-lo no DataGridCell uma vez dentro do conversor através do Parent propriedade no DataGridCell.

Para fazer isso, você precisará de um método auxiliar para encontrar os pais:

private T FindParent<T>(DependencyObject child)
    where T : DependencyObject
{
    T parent = VisualTreeHelper.GetParent(child) as T;  
    if (parent != null)
        return parent;
    else
        return FindParent<T>(parent);
}

Você pode optar por colocar esse código em um local reutilizável ou até mesmo torná-lo um método de extensão, mas aqui está como você o chama uma vez no conversor:

DataGrid parentDataGrid = FindParent<DataGrid>(dataGridCell);

Outras dicas

Eu imagino que você poderia usar um RelativeSource Binding para alcançar sua exigência.Experimente isto:

<Style TargetType="{x:Type DataGridCell}" x:Key="cellStyle" >
    <Setter Property="helpers:SearchBehaviours.IsTextMatchFocused">
        <Setter.Value>
            <MultiBinding Converter="{StaticResource SelectedSearchValueConverter}" FallbackValue="False">
                <Binding RelativeSource="{x:Static RelativeSource.Self}"/>
                <Binding Source="{x:Static helpers:MyClass.Instance}" Path="CurrentCellMatch" />
<!-- ----> -->  <Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGrid}}"/>
            </MultiBinding>
        </Setter.Value>
    </Setter>
</Style>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top