C# WPF XAML绑定不更新

C# WPF XAML绑定不更新,c#,wpf,binding,C#,Wpf,Binding,我有一个WPF项目,其中有4个TextBlock。我想要的是通过Binding更改每个TextBlock的文本 到目前为止,我有我的XAML: 在我的代码中,我有: 公共部分类主窗口:窗口 { 公共字符串FirstString{get;set;} 公共字符串SecondString{get;set;} 公共字符串第三个字符串{get;set;} 公共字符串第四个字符串{get;set;} 公共主窗口() { 初始化组件(); FirstString=“First”; SecondString

我有一个WPF项目,其中有4个
TextBlock
。我想要的是通过
Binding
更改每个
TextBlock
文本

到目前为止,我有我的XAML:


在我的代码中,我有:

公共部分类主窗口:窗口
{
公共字符串FirstString{get;set;}
公共字符串SecondString{get;set;}
公共字符串第三个字符串{get;set;}
公共字符串第四个字符串{get;set;}
公共主窗口()
{
初始化组件();
FirstString=“First”;
SecondString=“Second”;
ThirdString=“第三”;
第四字符串=“第四”;
}
}
但是
绑定根本不起作用。我做错什么了吗

编辑: 按照Chris Mantle在评论中的建议查看调试输出(我必须为绑定启用警告),我得到以下错误:

System.Windows.Data信息:10:无法使用绑定检索值,且不存在有效的回退值;改为使用默认值。BindingExpression:Path=FirstString;DataItem=null;目标元素是“TextBlock”(Name='First');目标属性为“Text”(类型为“String”)


除非另有规定,否则绑定的路径是相对于元素的
DataContext
。在您的情况下,我怀疑您根本没有指定
DataContext

由于属性是在
main窗口
类本身中声明的,因此最简单的修复方法是添加:

DataContext = this;

在构造函数的末尾。

由于您没有通知
第一个字符串
第二个字符串
第三个字符串
第四个字符串
已更改,因此更改不会反映在UI中。您可以实现
INotifyPropertyChanged
,也可以处理
dependencProperty

也设置您的
Datacontext

IMHO
dependencProperty
更适合此用途。以下是一个例子:

public partial class MainWindow : Window
{
    #region Public
    public string FirstString
    {
        get { return (string)GetValue(FirstStringProperty); }
        set { SetValue(FirstStringProperty, value); }
    }
    public string SecondString
    {
        get { return (string)GetValue(SecondStringProperty); }
        set { SetValue(SecondStringProperty, value); }
    }
    public string ThirdString
    {
        get { return (string)GetValue(ThirdStringProperty); }
        set { SetValue(ThirdStringProperty, value); }
    }
    public string FourthString
    {
        get { return (string)GetValue(FourthStringProperty); }
        set { SetValue(FourthStringProperty, value); }
    }

    #region Dependency Properties
    public static readonly DependencyProperty FirstStringProperty = DependencyProperty.Register("FirstString", typeof(string), typeof(MainWindow), new PropertyMetadata("default value"));
    public static readonly DependencyProperty SecondStringProperty = DependencyProperty.Register("SecondString", typeof(string), typeof(MainWindow), new PropertyMetadata("default value"));
    public static readonly DependencyProperty ThirdStringProperty = DependencyProperty.Register("ThirdString", typeof(string), typeof(MainWindow), new PropertyMetadata("default value"));        
    public static readonly DependencyProperty FourthStringProperty = DependencyProperty.Register("FourthString", typeof(string), typeof(MainWindow), new PropertyMetadata("default value"));
    #endregion
    #endregion

    public MainWindow()
    {
        InitializeComponent();    

        FirstString = "First";
        SecondString = "Second";
        ThirdString= "Third";
        FourthString= "Fourth";

        this.DataContext = this;
    }
}

有几件事是不正确的。
Binding
标记将查看控件的
DataContext
属性中的对象。除非另有指定,否则此属性从声明的父级继承
DataContext
。对于
窗口
控件,这是开箱即用的
null

这个问题有两种选择。您可以在代码隐藏或XAML中明确设置
DataContext

// In XAML
<Window DataContext={Binding RelativeSource={RelativeSource Self}}>

or

// In the code-behind
DataContext = this;

我建议您创建另一个类MainWindowViewModel

public class MainWindowViewModel
{
    public string FirstString { get; set; }
    public string SecondString { get; set; }
    public string ThirdString { get; set; }
    public string FourthString { get; set; }

    public MainWindowViewModel()
    {    
        FirstString = "First";
        SecondString = "Second";
        ThirdString= "Third";
        FourthString= "Fourth";
    }
}
然后在调用window类上的show之前设置MainWindow对象的DataContext

MainWindow wnd = new MainWindow();
wnd.DataContext = new MainWindowViewModel();
wnd.Show();

您可以通过从App.xaml中删除StartupUri=“MainWindow.xaml”来完成最后一点,并通过覆盖App.xaml.cs中的OnStartup来手动创建和显示主窗口。

应该是这样工作的

<Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <TextBlock x:Name="First" Text="{Binding FirstString}" Grid.Row="0"/>
            <TextBlock x:Name="Second" Text="{Binding SecondString}" Grid.Row="1"/>
            <TextBlock x:Name="Third" Text="{Binding ThirdString}" Grid.Row="2"/>
            <TextBlock x:Name="Fourth" Text="{Binding FourthString}" Grid.Row="3"/>
        </Grid>

输出窗口中有什么东西吗?什么都没有。我找不到原因。你能在输出窗口中打开数据绑定信息,看看是否还有更多细节吗?(工具菜单–>选项–>调试–>输出窗口–>WPF跟踪设置–>数据绑定,设置为Verbose或All)谁是窗口的数据上下文。应该是这样,我使用了DataContext=this;但仍然没有。移动InitializeComponent();在构造器的底部,您至少应该看到一些东西。不过尼古拉斯是对的,你写的DataContext=this;将其移至底部无需执行此操作,因为代码位于xaml后面,当上下文发生更改时,它将自动通知…@Arun我没有遵循您的逻辑。如果属性不是INPC属性,也不是依赖属性,则对属性的更改不会反映到UI中。在这种简单的情况下,在设置属性后设置
DataContext=this
将起作用,因为
DataContext
是一个依赖属性。但代码中的任何进一步更改都不会反映出来。@oimitro这是一个非常做作的示例,可以工作。但要注意,这远远不是最佳实践。您通常会有另一个对象(我们称之为视图模型)来实现该接口,该对象将被分配到视图的(本例中为窗口)
DataContext
。如果您想在WPF的上下文中阅读有关MVVM模式的更多信息,可以查看。@Sinon Belanger MainWindowViewModel.Oh类上没有InitializeComponent()方法。很抱歉没有意识到这是一个视图模型。删除我的评论。您的示例中缺少第二个引号,位于
ThirdString=“Third
<Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <TextBlock x:Name="First" Text="{Binding FirstString}" Grid.Row="0"/>
            <TextBlock x:Name="Second" Text="{Binding SecondString}" Grid.Row="1"/>
            <TextBlock x:Name="Third" Text="{Binding ThirdString}" Grid.Row="2"/>
            <TextBlock x:Name="Fourth" Text="{Binding FourthString}" Grid.Row="3"/>
        </Grid>
public string FirstString { get; set; }
public string SecondString { get; set; }
public string ThirdString { get; set; }
public string FourthString { get; set; }

public MainWindow()
{
    InitializeComponent();    

    FirstString = "First";
    SecondString = "Second";
    ThirdString = "Third";
    FourthString= "Fourth";
    this.DataContext = this;  //here you set the context to current instance of window

}