Если вы создаете привязку в коде позади, вы можете заставить его работать. Например, простой код, генерируемый связывание:
Binding binding = new Binding("BindingPath");
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(textBoxName, TextBox.TextProperty, binding);
Поскольку путь в этом связывания («BindingPath») это просто строка, эта строка может исходить из любого доступного объекта.
Вам нужно будет подключиться к созданию элементов данных, чтобы установить эти привязки.
Другая возможность на основе ваших комментариев:
This blog post описывает способ создания пользовательского связывания класса, унаследовав от MarkupExtension. Возможно, вы сможете использовать это как отправную точку, чтобы включить мое предложение в многоразовую разметку xaml для вашего специального случая привязки.
Больше мысли:
Ладно, это была интересная проблема, поэтому я решил потратить немного времени, видя, если я мог придумать с рабочим раствором. Я заранее извиняюсь за длину следующих образцов кода ...
Базируясь мое решение на блоге я связан выше I создал этот класс:
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:
<TextBox Text="{local:IndirectBinder IndirectProperty=FieldValuePath}"/>
Где TextBox может быть любой класс, который наследуется от контроля и текста может быть любое свойство зависимостей.
Очевидно, что если вам нужно выставить какие-либо другие параметры привязки данных (например, привязку к одному или двум каналам), вам нужно добавить дополнительные свойства в класс.
Хотя это сложное решение, одно преимущество, которое он использует при использовании конвертера, заключается в том, что привязка, которая, наконец, создана, противоречит фактическому внутреннему свойству, а не объекту. Это означает, что он правильно реагирует на события PropertyChanged.
ну, это подход, который может работать, но мне бы очень хотелось иметь возможность создавать привязки в XAML, потому что я планирую писать, имеют разные свойства привязки в зависимости от состояния базовых данных. Но, возможно, я действительно мог бы попытаться написать всю эту логику в коде ... – arconaut
и, кроме того, это не только TextBlock, что я планирую указать привязку. Он должен быть редактором/зрителем для любого свойства на любом объекте. Я думаю, что я должен добавить в топ-пост. – arconaut
спасибо за ответ, и спасибо за ссылку. Я собираюсь попробовать это – arconaut