为什么我不能绑定字符串?



试图将我的旧大脑包裹在WPF数据绑定上。从我能想到的最简单的场景开始:一个有效的在线示例,然后我简化了它

我将一个简单的string属性绑定到一个TextBlock。没用。当我把string封装在自己的类中时,它运行得很好!

问题:为什么我的string属性不起作用,而我的类起作用?

<Window x:Class = "DataBindingOneWay.MainWindow" 
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
Height = "350" Width = "600">
<Grid>
<StackPanel Orientation = "Vertical" HorizontalAlignment="Center" Margin="0,100,0,0">
<TextBlock Text="{Binding Name1}" />
</StackPanel>
</Grid>
</Window>
using System.Windows;
namespace DataBindingOneWay
{
public partial class MainWindow : Window
{
public class Employee
{
public string? Name1 { get; set; } = "Paul";
}
public string? Name1 { get; set; } = "Peter";
public MainWindow()
{
InitializeComponent();
DataContext = new Employee();
// DataContext = Name1;            
}
}
}

绑定操作在通过DataContext属性从FrameworkElement派生的元素上设置的数据上下文上。数据上下文是在元素树中继承的。

在XAML元素上声明数据绑定时,它们通过查看其直接DataContext属性来解析数据绑定。数据上下文通常是绑定源值路径求值的绑定源对象。您可以在绑定中覆盖此行为,并设置特定的绑定源对象值。如果未设置承载绑定的对象的DataContext属性,则会检查父元素的DataContext特性,依此类推,直到XAML对象树的根。简而言之,用于解析绑定的数据上下文是从父对象继承的,除非在对象上显式设置。

如果没有数据上下文集,或者需要将其他元素引用为绑定源,则需要使用SourceElementNameRelativeSource参数化Binding

绑定可以配置为使用特定对象进行解析,而不是使用数据上下文进行绑定解析。

让我们回顾一下如何绑定MainWindow中定义的属性。最初没有分配任何数据上下文。因此,到Name1的所有绑定都将失败。我们能做什么?以下是一些选项(还有更多)。

  • 在代码隐藏中将MainWindowDataContext设置为this

    public MainWindow()
    {
    InitializeComponent();
    DataContext = this;            
    }
    

    这意味着所有控件都继承MainWindow作为绑定源。因此,我们可以像这样绑定Name1属性:

    <TextBlock Text="{Binding Name1}"/>
    

    这里Name1是要在绑定源上绑定的属性的名称(或属性路径)。因此,如果我们简单地将Name1直接指定为窗口的DataContext,那么我们将需要引用绑定源本身,这就是没有属性路径的{Binding}所做的。

    public MainWindow()
    {
    InitializeComponent();
    DataContext = Name1;            
    }
    
    <TextBlock Text="{Binding}"/>
    
  • 如果未设置DataContext,则仍然可以使用ElementName(需要分配给目标控件的x:Name)或RelativeSource引用元素,CCD_25指代从当前元素遍历父元素到根元素的元素树中的元素。

    <TextBlock Text="{Binding Name1, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}"/>
    

    此示例转换为:在元素树上搜索类型为MainWindow的绑定源,如果找到它,则绑定到它的Name1属性。正如您所看到的,如果像您的示例中那样在控件本身上定义属性,则不一定需要数据上下文。尽管如此,如果没有任何东西可以阻止DataContext属性,通常您会使用它,因为它是方便地继承的。

我希望你看到它没有什么真正神奇的地方。关于具有约束力的sytax(可能会令人困惑),有一个很好的文档应该会消除你的很多问号:

  • 绑定路径语法
  • 数据绑定概述(WPF.NET)

我开始思考:字符串类中的哪个字段,或者更确切地说,属性实际上包含字符串的"值"?

奖励回合:您根本不需要担心。您绑定到string属性,WPF知道如何显示它,不需要使用内部结构,但出于教育目的,文档指出:

字符串是用于表示文本的字符的顺序集合。CCD_ 30对象是表示字符串的CCD_ 31对象的顺序集合;32对象对应于UTF-16代码单元。String对象的值是System.Char对象的顺序集合的内容,并且该值是不可变的(即,它是只读的)。

string类型使用其索引器属性Chars公开此字符数组。

因为在绑定到字符串时,要绑定到的对象内部没有Name1。也就是说,在Name1内部没有Name1(Name1.Name1的结果是什么?)。然而,在Employee对象内有一个Name1(Employee.Name1的结果是什么?)

如果要访问MainWindowName1属性,应将DataContext设置为this(它是MainWindow实例),而不是Name1

using System.Windows;
namespace DataBindingOneWay
{
public partial class MainWindow : Window
{
public class Employee
{
public string? Name1 { get; set; } = "Paul";
}
public string? Name1 { get; set; } = "Peter";
public MainWindow()
{
InitializeComponent();
DataContext = this;            
}
}
}

或者从另一方面-当您希望Name1属性设置为MainWindowDataContext时,您的绑定应该如下所示:

<Window x:Class = "DataBindingOneWay.MainWindow" 
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
Height = "350" Width = "600">
<Grid>
<StackPanel Orientation = "Vertical" HorizontalAlignment="Center" Margin="0,100,0,0">
<TextBlock Text="{Binding}" />
</StackPanel>
</Grid>
</Window>

多亏了Jonathan鼓舞人心的回应,我开始思考:字符串类中的哪个字段,或者更确切地说,属性实际上保存了字符串的"值"?

我玩了所有的东西,但似乎没有什么能控制住真正的弦!(奇怪)。这就是为什么我有了一个疯狂的想法,并尝试了简单的

<TextBlock Text="{Binding}" />

DataContext = Name1;            

而且。。。成功了!

最新更新