我如何绑定Binding.Path属性基础数据? [英] How do I bind the Binding.Path property to underlying data?

查看:240
本文介绍了我如何绑定Binding.Path属性基础数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想给TextBlock的Text属性绑定在一个非常动态的方式。我需要从一个底层的对象获取路径。

I'm trying to bind a TextBlock's Text property in a very dynamic way. I need to get the Path from an underlying object.

下面是DataTemplate中:

Here's the DataTemplate:

<DataTemplate DataType={x:Type local:DummyClass}>
  <TextBlock Text={Binding Path=???} />
</DataTemplate>

该DummyClass对象都有一个名为FieldValuePath属性 - 需要被放在那里的路径???是。

The DummyClass object has a property named "FieldValuePath" - the path that needs to be put where the ??? is.

这背后的想法是,该数据模板被认为是一个GUI观看/编辑任何对象的任何属性。因此,它是一种preferable才能够申报XAML这将绑定一些控件(文本框,的TextBlocks,datepickers等),以给定的属性。

The idea behind this is that the data template is supposed to be a GUI for viewing/editing any property of any object. So it's kind of preferable to be able to declare XAML which would bind some controls (textboxes, textblocks, datepickers, etc) to a given property.

也许任何人有关于如何实现这样的事情有什么建议?

Maybe anyone has any suggestions on how to implement such thing?

推荐答案

如果您创建的背后,code绑定,那么你可以得到它的工作。例如,一个简单的code生成的绑定是:

If you create the binding in the code behind then you could get it to work. For example a simple code generated binding is:

Binding binding = new Binding("BindingPath");
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(textBoxName, TextBox.TextProperty, binding);

由于这种结合(BindingPath)的路径只是一个字符串,该字符串可以来自任何可用的对象。

Since the path in this binding ("BindingPath") is just a string, that string could come from any available object.

您将需要挂接到创建你的数据项来设置这些绑定,虽然中。

You'll need to hook into the creation of your data items to set these binding though.


根据您的意见还有一种可能:

A further possibility based on your comments:

本博客文章概括的方式来创建一个自定义绑定类通过继承的MarkupExtension。您可以以此为出发点来包装我的建议成一个可重用的XAML标记为您的特殊约束的情况下。

This blog post outlines a way to create a custom binding class by inheriting from MarkupExtension. You may be able to use this as a starting point to wrap my suggestion into a reusable xaml markup for your special binding case.


更多的想法:

好了,这是一个有趣的问题,所以我决定花一点时间看,如果我能与工作解决方案上来。我提前为以下code样品的长度...

Okay, this was an interesting problem, so I decided to spend a little time seeing if I could come up with a working solution. I apologise in advance for the length of the following code samples...

此基础上我的博客中,我联系到上面我的解决方案,将创建此类:

Basing my solution on the blog post I linked to above I created this class:

public class IndirectBinder : MarkupExtension
    {
        public string IndirectProperty { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            //try to get bound items for our custom work
            DependencyObject targetObject;
            DependencyProperty targetProperty;
            bool status = TryGetTargetItems(serviceProvider, out targetObject, out targetProperty);

            if (status)
            {
                Control targetControl = targetObject as Control;
                if (targetControl == null) return null;

                //Find the object to take the binding from
                object dataContext = targetControl.DataContext;
                if (dataContext == null) return null;

                //Reflect out the indirect property and get the value
                PropertyInfo pi = dataContext.GetType().GetProperty(IndirectProperty);
                if (pi == null) return null;

                string realProperty = pi.GetValue(dataContext, null) as string;
                if (realProperty == null) return null;

                //Create the binding against the inner property
                Binding binding = new Binding(realProperty);
                binding.Mode = BindingMode.TwoWay;
                BindingOperations.SetBinding(targetObject, targetProperty, binding);

                //Return the initial value of the binding
                PropertyInfo realPi = dataContext.GetType().GetProperty(realProperty);
                if (realPi == null) return null;

                return realPi.GetValue(dataContext, null);

            }

            return null;

        }

        protected virtual bool TryGetTargetItems(IServiceProvider provider, out DependencyObject target, out DependencyProperty dp)
        {
            target = null;
            dp = null;
            if (provider == null) return false;

            //create a binding and assign it to the target
            IProvideValueTarget service = (IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget));
            if (service == null) return false;

            //we need dependency objects / properties
            target = service.TargetObject as DependencyObject;
            dp = service.TargetProperty as DependencyProperty;
            return target != null && dp != null;
        }

您可以使用这个新的标记与下面的XAML代码:

You can use this new markup with the following xaml:

<TextBox Text="{local:IndirectBinder IndirectProperty=FieldValuePath}"/>

在哪里文本框可以是任何类,从控制和文本继承可以是任何依赖项属性。

Where TextBox can be any class that inherits from control and Text can be any dependency property.

显然,如果你需要公开任何其他数据绑定选项(如单向或双向绑定),那么你就需要更多的属性添加到类。

Obviously if you need to expose any of the other databinding options (such as one or two way binding) then you'll need to add more properties to the class.

虽然这是一个复杂的解决方案,一个优点在于它具有比使用一个转换器是结合该最终创建是针对实际内属性而不是对象。这意味着,它正确地作出反应的PropertyChanged事件

While this is a complicated solution, one advantage that it has over using a converter is that the binding that is finally created is against the actual inner property rather than the object. This means that it correctly reacts to PropertyChanged events.

这篇关于我如何绑定Binding.Path属性基础数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆