1

好的...我是一个 VB.NET WinForms 人,试图了解 WPF 及其所有精彩。我正在编写一个基本的应用程序作为学习经验,并且一直在阅读大量信息并观看教程视频,但是我无法通过简单的 DataBinding 起步,而且我知道我缺少一些基本概念。尽管我很喜欢它,但我没有那个“啊哈!” 审查源代码的那一刻。

所以...在我的 Window 类中,我定义了一个自定义字符串属性。当我进入 Blend 时,我尝试将我的 TextBox 的文本数据绑定到这个属性,但我的属性在 Blend 中没有显示为可用于绑定的东西。

有人可以告诉我我需要在下面的代码/XAML 中添加什么……最重要的是为什么?

我的 XAML:

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <TextBox Text="How do I Bind my SomeText property here?"></TextBox>
    </Grid>
</Window>

我的窗口代码:

Class Window1 

    Private _sometext As String = "Hello World"

    Public Property SomeText() As String
        Get
            Return _sometext
        End Get
        Set(ByVal value As String)
            _sometext = value
        End Set
    End Property

End Class
4

4 回答 4

6

这是您需要更改 XAML 的方法(代码很好)。

<Window x:Class="Window1"    
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    
            Title="Window1" Height="300" Width="300" 
            DataContext="{Binding RelativeSource={RelativeSource Self}}">    
      <Grid>        
          <TextBox Text="{Binding SomeText}">
          </TextBox>    
      </Grid>
    </Window>

要了解 WPF 中的绑定,您需要了解 DataContext。每个元素都有一个 DataContext 属性,并且您放入该属性中的任何对象都将成为任何未指定显式数据源的绑定的数据源。DataContext 的值是从父对象继承的(因此在这种情况下,TextBox 继承了 Grid 的 DataContext,后者继承了 Window 的 DataContext)。既然要引用窗口的某个属性,就需要设置DataContext指向Window实例,这就是我在Window的DataContext属性中所做的。

您还可以使用 {Binding } 元素中的 Source= 或 RelativeSource= 语法更改单个绑定的数据源。

于 2008-10-17T12:52:02.757 回答
5

对于数据绑定,考虑以下几点很有帮助:

  1. 源对象
  2. 目标对象(必须是 DependencyObject)
  3. 源属性(源对象上参与绑定的属性)
  4. 目标属性(必须是依赖属性)

在您的示例代码中:

  1. 源对象 = Window1
  2. 目标对象 = 文本框
  3. 源属性 = SomeText 属性
  4. 目标属性 = 文本

Binding 标记扩展位于 Target 对象的 Target 属性上。

这是说明上述情况的图片:

替代文字

查看以下代码(解决此问题的一种方法):

<Window
    x:Class="WpfApplication2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="theWindow"
    Title="Window1"
    Height="300"
    Width="300"
>
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding ElementName=theWindow, Path=SomeText}"/>
            <Button
                Width="100"
                Height="25"
                Content="Change Text"
                Click="Button_Click"
            />
        </StackPanel>
    </Grid>
</Window>

在 Binding 标记扩展中,我使用 ElementName ... 定义了源,它允许您使用可视树中的另一个元素作为源。这样做时,我还必须使用 x:Name 属性为窗口命名。

有几种方法可以使用 Binding 定义源(即 Source、ElementName、DataContext)... ElementName 只是一种方法。

需要注意的一点是 Source 属性不必是 Dependency Property,但如果不是,那么 Target 属性将不会更新......没有一些特殊帮助。查看以下代码(我很抱歉它是 C#,这对我来说更快)。在其中你会看到我实现了 INotifyPropertyChanged。这允许源对象说某事发生了变化......并且数据绑定足够智能以观察它。因此,如果您单击按钮(来自此处的示例代码),它将更新 TextBox。如果不实现此接口(并且如果您单击按钮),TextBox 将不会更新。

我希望这会有所帮助。

/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window, INotifyPropertyChanged
{
    public Window1()
    {
        InitializeComponent();
    }

    private string _someText = "Hello World!";
    public string SomeText
    {
        get { return _someText; }
        set
        {
            _someText = value;
            OnNotifyPropertyChanged("SomeText");
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnNotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #endregion

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.SomeText = "Goodbye World!";
    }
}
于 2008-10-17T13:01:47.543 回答
1

WPF DataBinding 是一个非常强大的功能。我建议阅读网络上已有的一些文章,例如

Beatrix Costa 关于数据绑定的博客对我也很有帮助。

于 2008-10-17T13:02:05.360 回答
0

与 CLR 属性的数据绑定需要一个额外的步骤。您必须实现 INotifyPropertyChanged 并在 CLR 属性更改时触发 PropertyChanged 事件。这不会使它出现在 Blend 中,但您可以使用 Text="{Binding SomeText}" 绑定到属性并将窗口的 DataContext 设置为您的对象。

有一个替代方案。不要使用 .NET 数据绑定,而是考虑更新控件 .NET。它是一个替代数据绑定的开源项目,不需要 INotifyPropertyChanged。Update Controls 的伟大之处在于它可以看穿中间业务逻辑。使用 INotifyPropertyChanged,您必须捕获并重新触发事件。

于 2008-12-29T14:26:33.780 回答