绑定简单的WPF文本框文本TwoWay
我非常抱歉,这个问题是非常基本的。我刚刚学会了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”。
我在这里做错了什么?我错过了什么让绑定工作?
问题是,你不绑定到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
作为一个初来乍到WPF,这一切的绑定和DataContext的爵士可能会相当混乱。让我们先从你的绑定表达式首先...
<TextBox Text="{Binding Path=str, Mode=TwoWay}"/>
这是什么要说的是,你想你的Text属性绑定到无论TextBox
的DataContext
是。 DataContext
本质上是您的TextBox
从中获取数据的“事情”。现在这是蹭。 DataContext
如果未明确设置,则从视觉树中的“上方”元素继承。在您的代码中,TextBox
从Grid
元素继承它的DataContext
,该元素继而从Window
元素继承它的DataContext
。鉴于DataContext
未在您的Window
中设置,将应用DataContext
属性的默认值,即null
。 DataContext
也未在窗口的任何子元素中设置,它们通过继承将该窗口的所有子项的DataContext
设置为null
。
重要的是要注意,您在绑定表达式中忽略了Source
属性。
<TextBox Text="{Binding Source=left_out, Path=str, Mode=TwoWay}"/>
当该属性被遗漏,绑定源隐含为元素DataContext
,在这种情况下为空,基于上述的理由。基本上,你的表达在这里说的是,你想要绑定您的文本属性DataContext.str
由WPF解决的是null.str
。
好的,很酷。现在,我们如何设置您的TextBox.Text
的DataContext
绑定到该窗口的代码隐藏,所以我们可以得到str
属性?有几种方法可以做到这一点,但出于我们的目的,我们将专注于在TextBox.Text
属性的绑定中明确地设置它。现在,绑定有三种不同的“源”类型属性。 “源”是我们希望我们的控件/元素的绑定从其获取数据的位置。我们有Source
,RelativeSource
和ElementName
。我们只在这里专注于ElementName
,但其他人对研究和理解至关重要。
因此,让我们命名我们的Window
元素,以便我们可以通过ElementName
属性访问它。
<Window x:Class="WpfApplication1.MainWindow"
x:Name="_window"
...
现在,我们可以设置在TextBox.Text
的ElementName
属性绑定来引用窗口。
<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
,Binding
和DependencyProperty
,因为这些是WPF的核心。祝你好运!
感谢您花时间向我解释。那么这是否意味着如果我为“绑定源”设置一个“DataContext”以使其作为替代方案工作?在你的例子中,我可以设置“{绑定源= _window ...}”并使其工作? – kurakura88
非常欢迎。感谢您的帮助!至于你的问题,答案是否定的。 'ElementName'属性是唯一可以与'Window'的'x:Name'属性一起使用的属性。 '源'用于静态和动态资源,这是更先进一点。 –
它可能有助于设想'源'只是明确解析绑定对象或“源”的三种方法之一。我知道这很混乱。你可以使用'Source','RelativeSource'或'ElementName',它们都是互斥的。您也可以不使用这些,并将“源”区域留为空白,并将其解析为“DataContext”。注意'Source'和“Source”之间的区别。 “Source”是绑定的实际属性,“Source”是用于引用绑定的基础源对象的语义。 –
或者你可以设置你的DataContext到这个,但这真是个坏主意。你应该分开你的ViewModel和你的视图。 –
因此,设置DataContext解决了这个问题。无论如何,我可以使它工作而不必实例化一个对象,直接使用字符串属性?这个问题的答案是将DataContext设置为这个吗? – kurakura88
你可以绑定到窗口后面的代码,没有什么错:'public MainWindow {InitializeComponent(); ** DataContext = this; **}' – slugster