是否可以将绑定的Path属性绑定到另一个属性?
我想实现以下代码:
Text="{Binding Path={Binding Path=CurrentPath}}"
所以我可以动态调整我的实际绑定所引用的属性。谢谢你的帮助,Jonny。
是否可以将绑定的Path属性绑定到另一个属性?
我想实现以下代码:
Text="{Binding Path={Binding Path=CurrentPath}}"
我自己解决了。
这是解决方案,希望能帮助到有和我一样问题的人。
public class CustomBindingBehavior : Behavior<FrameworkElement>
{
public bool IsBinding
{
get
{
return (bool)GetValue(IsBindingProperty);
}
set
{
SetValue(IsBindingProperty, value);
}
}
public string PropertyPath
{
get
{
return (string)GetValue(PropertyPathProperty);
}
set
{
SetValue(PropertyPathProperty, value);
}
}
public static DependencyProperty
PropertyPathProperty = DependencyProperty.Register("PropertyPath", typeof(string),
typeof(CustomBindingBehavior), null);
public static DependencyProperty
IsBindingProperty = DependencyProperty.Register("IsBinding", typeof(bool),
typeof(CustomBindingBehavior), null);
protected override void OnAttached()
{
if (AssociatedObject is TextBlock)
{
var tb = AssociatedObject as TextBlock;
tb.Loaded += new RoutedEventHandler(tb_Loaded);
}
}
private void tb_Loaded(object sender, RoutedEventArgs e)
{
AddBinding(sender as TextBlock, TextBlock.TextProperty);
}
private void AddBinding(DependencyObject targetObj, DependencyProperty targetProp)
{
if (IsBinding)
{
Binding binding = new Binding();
binding.Path = new PropertyPath(this.PropertyPath, null);
BindingOperations.SetBinding(targetObj, targetProp, binding);
}
else
{
targetObj.SetValue(targetProp, this.PropertyPath);
}
}
}
以下是XAML中的实现:
<TextBlock >
<i:Interaction.Behaviors>
<behaviors:CustomBindingBehavior PropertyPath="{Binding Path=HeaderPropertyBinding}" IsBinding="{Binding Path=HeaderIsBinding}" />
</i:Interaction.Behaviors>
</TextBlock>
你好,Jonny
System.Windows.Interactivity
吗? - Sean C.正如其他帖子所提到的,你只能在依赖属性上设置绑定 - 而路径不是。根本原因是xaml是会被编译的源代码。在编译时,编译器不知道'CurrentPath'的值,并且无法编译。基本上,你想做的是运行时反射一个属性值 - 这可以使用你绑定的ViewModel中的另一个属性或使用转换器来完成。
ViewModel:
public string CurrentValue
{
get
{
var property = this.GetType().GetProperty(CurrentPath);
return property.GetValue(this, null);
}
}
使用转换器:
public class CurrentPathToValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var viewModel = (ViewModel)value;
var property = viewModel.GetType().GetProperty(viewModel.CurrentPath);
var currentValue = property.GetValue(viewModel, null);
return currentValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
当然,这些只适用于您想获取对象的简单属性 - 如果您想获取更复杂的内容,则反射代码将变得更加复杂。
除非您正在构建像属性网格这样的东西,或者因为某种原因您实际上想要自省运行在应用程序中的对象,否则我建议您重新审查设计,因为反射实际上只适用于少数情况。
private int _mySwitch;
//Set this to determine what the other property will return.
public int SwitchProperty
{
get { return _mySwitch; }
set
{
_mySwitch = value;
NotifyPropertyChanged("MySwitchableProperty");
}
}
public String PropertyA { get; set; }
public String PropertyB { get; set; }
//Bind to this property
public String MySwitchableProperty
{
get
{
switch (SwitchProperty)
{
case 1:
return PropertyA;
break;
case 2:
return PropertyB;
break;
default :
return String.Empty;
break;
}
}
}
Path不是一个依赖属性,因此绑定将无法工作。
我认为转换器可以帮助你。
例如:
第一个控件
Text="{Binding Path=CurrentPath}"
第二个控件
Text="{Binding Path=CurrentPath, Convertor={converters:MyConvertor}}"
进制转换器
public abstract class ConvertorBase<T> : MarkupExtension, IValueConverter
where T : class, new()
{
public abstract object Convert(object value, Type targetType, object parameter,
CultureInfo culture);
public virtual object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
#region MarkupExtension members
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_converter == null)
_converter = new T();
return _converter;
}
private static T _converter = null;
#endregion
}
我的转换器
public class MyConverter: ConvertorBase<MyConverter>
{
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (string)value.Equals("blabla") ? "Yes" : "No"; // here return necessary parametr
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}