我正在将WPF页面上的StackPanel中的FrameworkElement转移到以编程方式创建的StackPanel。在某一点上,我需要刷新绑定并获取属性值。
此时FrameworkElement.DataContext
具有正确的值,BindingExpression.Status==BindingStatus.Unattached
表示所有绑定表达式。我执行BindingExpression.UpdateTarget
,但属性值为空。
我找到了BindingExpression.UpdateTarget()的源代码:
public override void UpdateTarget()
{
if (Status == BindingStatus.Detached)
throw new InvalidOperationException(SR.Get(SRID.BindingExpressionIsDetached));
if (Worker != null)
{
Worker.RefreshValue(); // calls TransferValue
}
}
Worker在内部覆盖void BindingExpression.Activate()
中获取实例。同样在Activate()里面BindingExpression.Status设置为BindingStatus.Active。
如何以编程方式启动BindingExpression.Activate()
的执行并在此之后生成UpdateTarget?
这里的解决方案(谢谢,Olli):
public void UpdateAllBindingTargets( DependencyObject obj)
{
FrameworkElement visualBlock = obj as FrameworkElement;
if (visualBlock==null)
return;
if (visualBlock.DataContext==null)
return;
Object objDataContext = visualBlock.DataContext;
IEnumerable<KeyValuePair<DependencyProperty, BindingExpression>> allElementBinding = GetAllBindings(obj);
foreach (KeyValuePair<DependencyProperty, BindingExpression> bindingInfo in allElementBinding)
{
BindingOperations.ClearBinding(obj, bindingInfo.Key);
Binding myBinding = new Binding(bindingInfo.Value.ParentBinding.Path.Path);
myBinding.Source = objDataContext;
visualBlock.SetBinding(bindingInfo.Key, myBinding);
BindingOperations.GetBindingExpression(visualBlock, bindingInfo.Key).UpdateTarget();
}
}
获取对象的所有绑定:
public IEnumerable<KeyValuePair<DependencyProperty, BindingExpression>> GetAllBindings( DependencyObject obj)
{
var stack = new Stack<DependencyObject>();
stack.Push(obj);
while (stack.Count > 0)
{
var cur = stack.Pop();
var lve = cur.GetLocalValueEnumerator();
while (lve.MoveNext())
if (BindingOperations.IsDataBound(cur, lve.Current.Property))
{
KeyValuePair<DependencyProperty,BindingExpression> result=new KeyValuePair<DependencyProperty, BindingExpression>(lve.Current.Property,lve.Current.Value as BindingExpression);
yield return result;
}
int count = VisualTreeHelper.GetChildrenCount(cur);
for (int i = 0; i < count; ++i)
{
var child = VisualTreeHelper.GetChild(cur, i);
if (child is FrameworkElement)
stack.Push(child);
}
}
}
答案 0 :(得分:3)
您可以通过编程方式创建一个新的绑定,这应该可以解决问题。
http://msdn.microsoft.com/en-us/library/ms752347.aspx#creating_a_binding
来自MSDN页面的示例
MyData myDataObject = new MyData(DateTime.Now);
Binding myBinding = new Binding("MyDataProperty");
myBinding.Source = myDataObject;
myText.SetBinding(TextBlock.TextProperty, myBinding);