Binding the Path Property of a Binding

社会主义新天地 提交于 2019-12-17 20:26:34

问题


is it possible to bind the Path property of a binding to another property?

I want to realize this code:

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

So I can adjust dynamically to which Property my actual binding is refering.

Thanks for your Help Jonny


回答1:


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.




回答2:


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




回答3:


Path is not a dependency property, therefore the binding will not work.




回答4:


Perhaps you could bind to a property that returns another property based on a switch statement and bind to that. Change the 'switch' property and you change the output of the other property. Just don't forget to include your NotifyPropertyChanged stuff in the switch property for the bound property otherwise your view will not update. e.g.

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



回答5:


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


来源:https://stackoverflow.com/questions/13524588/binding-the-path-property-of-a-binding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!