DataGridをコンバーターに入れる方法
-
21-12-2019 - |
質問
このコンバータを持っています、現在のDataGridCell、DataGridCellInfoオブジェクトと私はそこにDataGridオブジェクトを取得しようとしています。
<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>
.
DataGridを以下のようにバインドするだけで、これが仮想化されているときにスクロールしてアイテムをリサイクルすると、バインディングがドロップされ、エラーが発生します。
System.Windows.Data警告:4:バインドのソースが見つかりません 参照 'ElementName= genericDataGrid'。 BindingExpression:path=; dataItem= null;ターゲット要素は 'DataGridCell'(name= '')です。目標 プロパティは 'istextmatchfocused'(タイプ 'boolean')
DataGridCellの下のコンバータはDataGridCellInfoにキャストされています。
これを行うにはDataGridオブジェクトが必要です。私は3つの解決策を見ることができます:
1. DataGridオブジェクトを使用する必要なしに、2つのDataGridCellInfoオブジェクトを比較して、それらが同じかどうかを確認することができます。 (私はこれを試してみましたが、常にfalseを返します)
2.実際のDataGridを親のように1つのDataGridCellInfoオブジェクトから取得します。 (これを行う方法がわかりません)。
3.さまざまな方法で作業しています。
明らかに、このコンバータは、バインディングの1つが変わるときはいつでも複数のセルに対して実行されますので、できるだけ効率的になります。
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;
}
}
. 解決
親戚緩命を介してコンバータに与えることのある解決策がありますが、それは異なる方法でも行うことができます。DataGridパラメータを渡すことはできませんが、その代わりにDataGridCellのParent
プロパティを介してConverterの内側にDataGridCellからそれを見つけます。
これを行うには、親検索ヘルパーメソッドが必要です。
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);
}
.
このコードを再利用可能な場所に入れることさえ選んだ、またはそれを拡張方法にしても、ここではコンバータ内で1回呼び出す方法です。
DataGrid parentDataGrid = FindParent<DataGrid>(dataGridCell);
. 他のヒント
あなたがあなたの要求を達成するためにRelativeSource Binding
を使うことができると想像します。これを試してください:
<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>
.