我很抱歉这个问题非常基本。我刚刚学习了WPF,但我没有简单的双向绑定到textbox.text到string属性。
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);
}
}
首先,文本框不显示&#34;确定&#34;,但它是空白的。然后,我在文本框中键入了一个不同的文本,例如:&#34; blablabla&#34;没有引号。然后我单击按钮检查我的str属性是否已更新。显然,str仍然包含&#34; OK&#34;。
我在这里做错了什么?我错过了什么才能使绑定工作?
答案 0 :(得分:5)
作为WPF的新手,所有这些Binding和DataContext爵士乐都会让人感到困惑。让我们首先从你的绑定表达式开始......
<TextBox Text="{Binding Path=str, Mode=TwoWay}"/>
这就是说你要将Text属性绑定到DataContext
的{{1}}。 TextBox
基本上是您DataContext
从中获取数据的“事物”。现在,这就是问题。如果未明确设置,TextBox
将继承自可视树中的“上方”元素。在您的代码中,DataContext
从TextBox
元素继承了DataContext
,Grid
元素继承了DataContext
元素中的Window
元素。如果未在DataContext
中设置Window
,则会应用DataContext
属性的默认值,即null
。 DataContext
也未在窗口的任何子元素中设置,通过继承,将该窗口的所有子项的DataContext
设置为null
。
请务必注意,您在绑定表达式中遗漏了Source
属性。
<TextBox Text="{Binding Source=left_out, Path=str, Mode=TwoWay}"/>
当省略此属性时,绑定的源隐含为元素DataContext
,在这种情况下为空,由于上述原因。基本上,你的表达在这里说的是你想要将你的文本属性绑定到DataContext.str
,由WPF解析的是null.str
。
DataContext
绑定的TextBox.Text
设置为窗口的Code Behind,以便我们可以获得str
属性?有几种方法可以做到这一点,但出于我们的目的,我们将专注于在TextBox.Text
属性的绑定中明确设置它。现在,绑定有三种不同的“源”类型属性。 “源”是我们希望我们的控件/元素绑定从中获取数据的地方。我们有Source
,RelativeSource
和ElementName
。我们只关注ElementName
这里,但其他人对研究和理解至关重要。
所以,让我们命名我们的Window
元素,以便我们可以通过ElementName
属性访问它。
<Window x:Class="WpfApplication1.MainWindow"
x:Name="_window"
...
现在我们可以在ElementName
绑定上设置TextBox.Text
属性来引用窗口。
<TextBox Text="{Binding ElementName=_window, Path=str, Mode=TwoWay}"/>
这意味着绑定将在尝试解析绑定时查找_window.str
属性。此时,您仍可能看不到str
中反映的TextBox
值。这是因为它的值是在窗口构造函数中的InitializeComponent
方法之后设置的。此功能是第一次解析绑定的位置。如果您在致电str
之前设置InitializeComponent
的值,您会看到TextBox
中反映的值。
这将我们带到依赖属性。现在,只需知道依赖属性已内置更改通知,您的绑定需要它,以便它“知道”绑定何时更改以及何时再次解析绑定值。是的,您可以在代码中使用INotifyPropertyChanged
,但在这种情况下使用DependencyProperties有很好的论据,这只会混淆此时的问题。但是,这是另一个必须理解的事情。
以下是DependencyProperty
媒体资源str
的代码。
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的核心。祝你好运!
答案 1 :(得分:3)
问题是,你不要绑定到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