2016-08-21 74 views
0

我非常抱歉,这个问题是非常基本的。我刚刚学会了WPF,并且我未能简单地将textbox.text的两种方式绑定到字符串属性。绑定简单的WPF文本框文本TwoWay

XAML代码:

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:WpfApplication1" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid x:Name="StuInfo"> 
    <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="10,26,0,0" TextWrapping="Wrap" Text="{Binding Path=str,Mode=TwoWay}" VerticalAlignment="Top" Width="120"/> 
    <Button x:Name="button" Content="Check" HorizontalAlignment="Left" Margin="10,67,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/> 
</Grid> 

C#代码

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     str = "OK"; 
    } 

    public string str { get; set; } 

    private void button_Click(object sender, RoutedEventArgs e) 
    { 
     Console.WriteLine(str); 
    } 
} 

首先,文本框不显示 “OK”,但它是空白。然后,我在文本框中输入了不同的文本,例如:“blablabla”没有引号。然后我点击按钮来检查我的str属性是否已经更新。显然,str仍然包含“OK”。

我在这里做错了什么?我错过了什么让绑定工作?

回答

1

问题是,你不绑定到Window的代码隐藏,而是绑定到DataContext。

试试这个:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new DC(); 
    } 

    public class DC 
    { 
     public string str { get; set; } 

     public DC() 
     { 
      str = "OK"; 
     } 
    } 
} 

通常情况下,你将有两个不同的文件,但对于测试,你可以在一个文件中做到这一点。 之后,您的DC(DataContext)应该实现INotifyPropertyChanged接口。

尝试查找有关MVVM一些文章这样http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial

+0

或者你可以设置你的DataContext到这个,但这真是个坏主意。你应该分开你的ViewModel和你的视图。 –

+0

因此,设置DataContext解决了这个问题。无论如何,我可以使它工作而不必实例化一个对象,直接使用字符串属性?这个问题的答案是将DataContext设置为这个吗? – kurakura88

+1

你可以绑定到窗口后面的代码,没有什么错:'public MainWindow {InitializeComponent(); ** DataContext = this; **}' – slugster

1

作为一个初来乍到WPF,这一切的绑定和DataContext的爵士可能会相当混乱。让我们先从你的绑定表达式首先...

<TextBox Text="{Binding Path=str, Mode=TwoWay}"/>

这是什么要说的是,你想你的Text属性绑定到无论TextBoxDataContext是。 DataContext本质上是您的TextBox从中获取数据的“事情”。现在这是蹭。 DataContext如果未明确设置,则从视觉树中的“上方”元素继承。在您的代码中,TextBoxGrid元素继承它的DataContext,该元素继而从Window元素继承它的DataContext。鉴于DataContext未在您的Window中设置,将应用DataContext属性的默认值,即nullDataContext也未在窗口的任何子元素中设置,它们通过继承将该窗口的所有子项的DataContext设置为null

重要的是要注意,您在绑定表达式中忽略了Source属性。

<TextBox Text="{Binding Source=left_out, Path=str, Mode=TwoWay}"/>

当该属性被遗漏,绑定源隐含为元素DataContext,在这种情况下为空,基于上述的理由。基本上,你的表达在这里说的是,你想要绑定您的文本属性DataContext.str由WPF解决的是null.str

好的,很酷。现在,我们如何设置您的TextBox.TextDataContext绑定到该窗口的代码隐藏,所以我们可以得到str属性?有几种方法可以做到这一点,但出于我们的目的,我们将专注于在TextBox.Text属性的绑定中明确地设置它。现在,绑定有三种不同的“源”类型属性。 “源”是我们希望我们的控件/元素的绑定从其获取数据的位置。我们有Source,RelativeSourceElementName。我们只在这里专注于ElementName,但其他人对研究和理解至关重要。

因此,让我们命名我们的Window元素,以便我们可以通过ElementName属性访问它。

<Window x:Class="WpfApplication1.MainWindow" 
     x:Name="_window" 
     ... 

现在,我们可以设置在TextBox.TextElementName属性绑定来引用窗口。

<TextBox Text="{Binding ElementName=_window, Path=str, Mode=TwoWay}"/>

这意味着绑定试图解决它绑定时会寻找_window.str财产。此时,您仍然可能看不到TextBox中反映的str值。这是因为它的值是在窗口构造函数中的InitializeComponent方法之后设置的。这个函数是第一次解析绑定的地方。如果您在致电InitializeComponent之前设置str的值,则会看到TextBox中反映的值。

这使我们看到依赖属性。现在,只知道依赖属性内置了更改通知,您的绑定需要它,以便它知道绑定已更改何时以及何时再次解析绑定值。是的,你可以在你的代码中使用INotifyPropertyChanged,但在这种情况下使用DependencyProperties有很好的参数,这只会混淆这个问题。但是,这是另一个必须理解的东西。

这里是您的str属性DependencyProperty的代码。

public static readonly DependencyProperty StrProperty 
    = DependencyProperty.Register("Str", typeof(string), typeof(MainWindow), 
     new FrameworkPropertyMetadata(FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 
public string Str 
{ 
    get{return (string)GetValue(StrProperty);} 
    set{SetValue(StrProperty,value);} 
} 

现在,你可以设置像这样的价值,并把它通过绑定到您TextBox反映。

public MainWindow() 
{ 
    InitializeComponent(); 
    Str = "OK"; 
} 

此时,一切都会好的。我希望这可以帮到你。我花了一段时间才得到WPF的支持。我的建议是尽可能多地阅读DataContext,BindingDependencyProperty,因为这些是WPF的核心。祝你好运!

+0

感谢您花时间向我解释。那么这是否意味着如果我为“绑定源”设置一个“DataContext”以使其作为替代方案工作?在你的例子中,我可以设置“{绑定源= _window ...}”并使其工作? – kurakura88

+0

非常欢迎。感谢您的帮助!至于你的问题,答案是否定的。 'ElementName'属性是唯一可以与'Window'的'x:Name'属性一起使用的属性。 '源'用于静态和动态资源,这是更先进一点。 –

+0

它可能有助于设想'源'只是明确解析绑定对象或“源”的三种方法之一。我知道这很混乱。你可以使用'Source','RelativeSource'或'ElementName',它们都是互斥的。您也可以不使用这些,并将“源”区域留为空白,并将其解析为“DataContext”。注意'Source'和“Source”之间的区别。 “Source”是绑定的实际属性,“Source”是用于引用绑定的基础源对象的语义。 –