Pregunta

Tengo este convertidor, se necesita:el DataGridCell actual, un objeto DataGridCellInfo y estoy intentando incluir el objeto DataGrid allí también.

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

Intenté simplemente vincular el DataGrid como se muestra a continuación; sin embargo, cuando se virtualiza, se desplaza hacia abajo y los elementos se reciclan, se elimina el enlace y se genera un error.

Advertencia de System.Windows.Data:4:No se puede encontrar la fuente para el enlace con la referencia 'ElementName = GenericDataGrid'.Expresión vinculante: Ruta =;Elemento de datos=nulo;el elemento de destino es 'DataGridCell' (Nombre='');La propiedad objetivo es 'istextMatchFocused' (tipo 'boolean')

En el convertidor a continuación, DataGridCell se convierte en DataGridCellInfo, y básicamente estoy comparando el índice de fila y columna de los dos DataGridCellInfo para ver si coinciden; de ser así, devuelve verdadero.

Para hacer esto necesito el objeto DataGrid.Puedo ver 3 posibles soluciones:
1.Tal vez pueda simplemente comparar los dos objetos DataGridCellInfo para ver si son iguales, sin tener que usar un objeto DataGrid.(He probado esto pero siempre devuelve falso)
2.Obtenga el DataGrid real de uno de los objetos DataGridCellInfo ya que es principal.(No sé cómo hacer esto).
3.Haga que la encuadernación funcione de una manera diferente.

Obviamente, este convertidor se ejecutará para varias celdas cada vez que cambie uno de los enlaces, por lo que me gustaría que fuera lo más eficiente posible.

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;
    }
}
¿Fue útil?

Solución

Aunque me gusta la solución dada de entregárselo al convertidor a través de RelativeSource, también se puede hacer de otra manera.Es posible no pasar un parámetro DataGrid, sino encontrarlo desde DataGridCell una vez dentro del convertidor a través de Parent propiedad en DataGridCell.

Para hacer esto, necesitará un método de ayuda para encontrar padres:

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

Puedes optar por poner este código en un lugar reutilizable, o incluso convertirlo en un método de extensión, pero así es como lo llamas una vez dentro del convertidor:

DataGrid parentDataGrid = FindParent<DataGrid>(dataGridCell);

Otros consejos

Me imagino que podrías usar un RelativeSource Binding para lograr su requisito.Prueba esto:

<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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top