Route/Tunnel 属性 值到另一个 属性 行为
Route/Tunnel property value to another property with a behavior
我有一个 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>
*RoutePropertyValueBehavior**
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));
}
实际上调试时Target
总是null
。此外,如果更改 DataGrid
内的顺序,则不会再次调用 SourceChangedCallback
。所以无论如何,将 'tunnel' 属性 值转换为另一个 属性.
的方法似乎是错误的
您可以绑定到目标对象,然后指定要设置的源 属性。每当设置任何目标属性时,您都应该尝试设置源 属性。试试这个:
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:
<behaviors:RoutePropertyValue
TargetObject="{Binding}"
TargetMember="Index"
Source="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=(ItemsControl.AlternationIndex)}"
/>
我有一个 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>
*RoutePropertyValueBehavior**
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));
}
实际上调试时Target
总是null
。此外,如果更改 DataGrid
内的顺序,则不会再次调用 SourceChangedCallback
。所以无论如何,将 'tunnel' 属性 值转换为另一个 属性.
您可以绑定到目标对象,然后指定要设置的源 属性。每当设置任何目标属性时,您都应该尝试设置源 属性。试试这个:
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:
<behaviors:RoutePropertyValue
TargetObject="{Binding}"
TargetMember="Index"
Source="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=(ItemsControl.AlternationIndex)}"
/>