我的程序包含此行的几个实例:
<local:MyClass Data="{Binding}"/>
即。属性Data
绑定到周围窗口的数据上下文。当窗口DataContext
的值发生变化时,绑定有时会更新,有时不会更新;它取决于<local:MyClass...>
在XAML文件中的位置。
以下是一个示例(编辑:我将{Binding}
更改为{Binding Path=DataContext, ElementName=myWindow}
以强调问题与DataContext
的继承无关:< / p>
XAML代码:
<Window x:Class="BindTest.MainWindow"
x:Name="myWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BindTest"
Title="Binding Test" Height="101" Width="328">
<Window.Tag>
<local:MyClass x:Name="bindfails" Data="{Binding Path=DataContext, ElementName=myWindow}"/>
</Window.Tag>
<StackPanel Orientation="Horizontal">
<Button Margin="5" Padding="5" Click="SetButtonClicked">Set DataContext</Button>
<Button Margin="5" Padding="5" Click="ReadButtonClicked">Read Bound Property</Button>
<local:MyClass x:Name="bindworks" Data="{Binding Path=DataContext, ElementName=myWindow}"/>
</StackPanel>
</Window>
C#代码:
using System.Windows;
namespace BindTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void SetButtonClicked(object sender, RoutedEventArgs e)
{
DataContext = 1234;
}
private void ReadButtonClicked(object sender, RoutedEventArgs e)
{
string txtA = (bindfails.Data == null ? "null" : bindfails.Data.ToString());
string txtB = (bindworks.Data == null ? "null" : bindworks.Data.ToString());
MessageBox.Show(string.Format("bindfails.Data={0}\r\nbindworks.Data={1}", txtA, txtB));
}
}
public class MyClass : FrameworkElement
{
#region Dependency Property "Data"
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(MyClass), new UIPropertyMetadata(null));
#endregion
}
}
首先按下按钮&#34;设置DataContext&#34;更改数据上下文。然后按下按钮&#34; Read Bound Property&#34;,显示以下消息:
bindfails.Data =空
bindworks.Data = 1234
显然,数据绑定仅针对MyClass
的子StackPanel
元素进行了更新;但未更新MyClass
引用的Window.Tag
元素的数据绑定。
EDIT2:我还发现,在MainWindow
的构造函数中以编程方式添加绑定时绑定有效:
Binding binding = new Binding("DataContext") {Source = this};
bindfails.SetBinding(MyClass.DataProperty, binding);
绑定仅在XAML中声明时失败。此外,问题并非针对DataContext
;当我使用其他Window
属性时也会发生这种情况,例如Title
。
任何人都可以解释这种行为并建议如何在这两种情况下允许在XAML中使用{Binding}
吗?
EDIT3:以上代码并不完全等同于{Binding}标记扩展。 100%等效代码是:
Binding binding = new Binding("DataContext") {ElementName = "myWindow"};
bindfails.SetBinding(MyClass.DataProperty, binding);
当我使用该代码时,绑定也会失败(例如在XAML中绑定时),并且以下诊断消息将写入调试输出:
System.Windows.Data错误:4:无法找到带引用的绑定源&#39; ElementName = myWindow&#39;。
显然,ElementName
属性只搜索可视树或逻辑树,即使WPF在线文档中没有记录这一点。可能没有简单的方法在XAML中设置这样的绑定。
答案 0 :(得分:1)
我认为它不起作用,因为当您编写{Binding}
时,要绑定的数据的上下文将从父级继承。对于bindworks,它是StackPanel
,从DataContext
继承Window
,但bindfails.Parent
属性为null
。
我想知道你为什么要把一个控件放在Window的标签元素中。如果由于某种原因必须将其保留在Tag
节点中,则可以直接更新其DataContext
,因此只需将SetButtonClicked
方法更改为:
private void SetButtonClicked(object sender, RoutedEventArgs e)
{
DataContext = 1234;
bindfails.DataContext = DataContext;
}
使其发挥作用的另一种简单方法是从bindfails
中取出Window.Tag
并将其放在Window
中的某个位置,即StackPanel
。
接下来,在Window的构造函数中,编写this.Tag = bindfails
。如果您不希望TextBox显示在表单中,可以将其Visibility
设置为Collapsed
(或将其放在折叠的容器控件中)。
答案 1 :(得分:1)
dataContext仅通过对象树传递。 Property标记不在可视树中,并且不会响应DataContext更改的Event,并且在没有此事件的情况下不会刷新绑定。
见: 依赖属性标识符字段:来自FrameworlElement的DataContextProperty
数据上下文是一个允许对象从对象树中的父对象继承绑定指定信息的概念
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.datacontext(v=vs.95).aspx