Wpf 将管线/隧道特性值转换为具有行为的另一个特性

Wpf 将管线/隧道特性值转换为具有行为的另一个特性,wpf,behavior,Wpf,Behavior,我有一个DataGrid,希望将AlternationIndex传递给当前对象的绑定元素 <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Grid> <TextBlock HorizontalAlignment="Center" Text="{Binding Index}"/> <i:Interaction.Be

我有一个DataGrid,希望将AlternationIndex传递给当前对象的绑定元素

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Grid>
            <TextBlock HorizontalAlignment="Center" Text="{Binding Index}"/>
            <i:Interaction.Behaviors>
                <behaviors:RoutePropertyValue 
                    Source="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=(ItemsControl.AlternationIndex)}"
                    Target="{Binding Index, Mode=TwoWay}"/>
            </i:Interaction.Behaviors>
        </Grid>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>
细胞模板

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Grid>
            <TextBlock HorizontalAlignment="Center" Text="{Binding Index}"/>
            <i:Interaction.Behaviors>
                <behaviors:RoutePropertyValue 
                    Source="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=(ItemsControl.AlternationIndex)}"
                    Target="{Binding Index, Mode=TwoWay}"/>
            </i:Interaction.Behaviors>
        </Grid>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>
*RoutePropertyValueBehavior**

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Grid>
            <TextBlock HorizontalAlignment="Center" Text="{Binding Index}"/>
            <i:Interaction.Behaviors>
                <behaviors:RoutePropertyValue 
                    Source="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=(ItemsControl.AlternationIndex)}"
                    Target="{Binding Index, Mode=TwoWay}"/>
            </i:Interaction.Behaviors>
        </Grid>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>
public class RoutePropertyValue : Behavior<FrameworkElement>
{
    /// <summary>
    /// The source property value
    /// </summary>
    public object Source
    {
        get => (object)GetValue(SourceProperty);
        set => SetValue(SourceProperty, value);
    }

    /// <summary>
    /// The <see cref="Source"/> DependencyProperty.
    /// </summary>
    public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(object), typeof(RoutePropertyValue), new PropertyMetadata(null, SourceChangedCallback));

    private static void SourceChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs args)
    {
        if (d is RoutePropertyValue instance)
        {
            instance.OnSourceChanged();
        }
    }

    protected virtual void OnSourceChanged()
    {
        Target = Source;
    }


    /// <summary>
    /// The target where the value should be writetn
    /// </summary>
    public object Target
    {
        get => (object)GetValue(TargetProperty);
        set => SetValue(TargetProperty, value);
    }

    /// <summary>
    /// The <see cref="Target"/> DependencyProperty.
    /// </summary>
    public static readonly DependencyProperty TargetProperty = DependencyProperty.Register("Target", typeof(object), typeof(RoutePropertyValue), new PropertyMetadata(null));

}

实际上,调试时目标始终为空。另外,如果在DataGrid内部更改顺序,则不会再次调用SourceChangedCallback。因此,无论如何,将属性值“隧道”到另一个属性似乎是错误的。您可以绑定到目标对象,然后指定要设置的源属性。无论何时设置任何目标属性,都应该尝试设置源属性。试试这个:

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Grid>
            <TextBlock HorizontalAlignment="Center" Text="{Binding Index}"/>
            <i:Interaction.Behaviors>
                <behaviors:RoutePropertyValue 
                    Source="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=(ItemsControl.AlternationIndex)}"
                    Target="{Binding Index, Mode=TwoWay}"/>
            </i:Interaction.Behaviors>
        </Grid>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>
public class RoutePropertyValue : Behavior<FrameworkElement>
{
    public object Source
    {
        get => GetValue(SourceProperty);
        set => SetValue(SourceProperty, value);
    }

    public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(nameof(Source), typeof(object), 
        typeof(RoutePropertyValue), new PropertyMetadata(null, Callback));

    private static void Callback(DependencyObject d, DependencyPropertyChangedEventArgs args)
    {
        if (d is RoutePropertyValue instance)
            instance.OnAnyValueChanged();
    }

    protected virtual void OnAnyValueChanged()
    {
        if (!string.IsNullOrEmpty(TargetMember))
            TargetObject?.GetType().GetProperty(TargetMember)?.SetValue(TargetObject, Source);
    }

    public object TargetObject
    {
        get => GetValue(TargetObjectProperty);
        set => SetValue(TargetObjectProperty, value);
    }

    public static readonly DependencyProperty TargetObjectProperty = DependencyProperty.Register(nameof(TargetObject), typeof(object), 
        typeof(RoutePropertyValue), new PropertyMetadata(null, Callback));

    public string TargetMember
    {
        get => (string)GetValue(TargetMemberProperty);
        set => SetValue(TargetMemberProperty, value);
    }

    public static readonly DependencyProperty TargetMemberProperty = DependencyProperty.Register(nameof(TargetMember), typeof(string),
        typeof(RoutePropertyValue), new PropertyMetadata(null, Callback));
}
XAML:

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Grid>
            <TextBlock HorizontalAlignment="Center" Text="{Binding Index}"/>
            <i:Interaction.Behaviors>
                <behaviors:RoutePropertyValue 
                    Source="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=(ItemsControl.AlternationIndex)}"
                    Target="{Binding Index, Mode=TwoWay}"/>
            </i:Interaction.Behaviors>
        </Grid>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

每个细胞?此模板仅在一个单元格中使用,因此仅在每个单元格和行上创建实例,如果Im错误,请更正我。我想实现的是,每个单元格都有一个组合框来选择索引!=它自己的。“编辑”后,我还需要每个元素的索引,并希望在DataGrid上再进行一次迭代,以获得依赖的索引。什么是索引?它是您的数据对象的属性吗?@mm8正是!索引应该是DataGrid的替代索引,并且在DataGrid上的数据对象更改其位置时始终设置/更新。是否可以直接在属性中写入TargetObject得到更新?是否要设置对象的属性。您不想将源属性绑定到目标属性。