4

是否可以将绑定的 Path 属性绑定到另一个属性?

我想实现这段代码:

Text="{Binding Path={Binding Path=CurrentPath}}"

所以我可以动态调整我的实际绑定所引用的属性。

感谢您的帮助强尼

4

5 回答 5

4

I worked it out on myself.

Heres the solution, I hope it might help anyone got the same problem like me.

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

And heres the implementation in XAML:

<TextBlock >
                <i:Interaction.Behaviors>
                    <behaviors:CustomBindingBehavior PropertyPath="{Binding Path=HeaderPropertyBinding}" IsBinding="{Binding Path=HeaderIsBinding}" />
                </i:Interaction.Behaviors>
            </TextBlock>

Greetings Jonny

于 2012-11-23T11:25:16.677 回答
2

As other posters have mentioned, you can only set a binding on a dependency property - which path is not. The underlying reason is that xaml is source code that gets compiled. At compile time the compiler has no idea what the value of 'CurrentPath' is, and would not be able to compile. Essentially what you are looking to do is runtime reflection of a property value - which could be done using another property in the ViewModel you are binding to, or using a converter.

ViewModel:

public string CurrentValue
{
    get
    {
         var property = this.GetType().GetProperty(CurrentPath);
         return property.GetValue(this, null);
    }
} 

Using a converter:

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

Of couse these only work if you want to get a simple property of the object - if you want to get something more complex your reflection code is going to get a lot more complex.

Unless you are building something like a property grid, or for some other reason you actually want to introspect the objects running in your application, I would suggest you revisit your design, as reflection is really only suited to a few situations.

于 2012-11-23T08:27:16.387 回答
1

Path 不是依赖属性,因此绑定将不起作用。

于 2012-11-23T07:22:56.123 回答
1

也许您可以绑定到基于 switch 语句返回另一个属性的属性并绑定到该属性。更改“开关”属性并更改另一个属性的输出。只是不要忘记在绑定属性的 switch 属性中包含您的 NotifyPropertyChanged 内容,否则您的视图将不会更新。例如

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;
        }
    }
}
于 2012-11-23T08:26:24.263 回答
0

I think converter can helps your. Expample

First control

Text="{Binding Path=CurrentPath}"

Second control

Text="{Binding Path=CurrentPath, Convertor={converters:MyConvertor}}"

Base converter

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
    }

MyConverter

 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;
        }
    }
于 2012-11-23T08:39:40.283 回答