WPF:将属性绑定到TextBlock不起作用

时间:2017-06-15 15:55:59

标签: c# wpf mvvm .net-3.5 inotifypropertychanged

我在xaml文件下面(这是一块):

                        <Grid Opacity="1" Margin="5">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />                                
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="Auto" />                                   
                            </Grid.ColumnDefinitions>

                            <Label Grid.Row="0" Grid.Column="0" Content="ID"/>
                            <Label Grid.Row="0" Grid.Column="1" Content="Name"/>
                            <Label Grid.Row="0" Grid.Column="2" Content="Description"/>                                

                            <TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding ID}"/>
                            <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Name}"/>
                            <TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding Description}"/>

                        </Grid>

数据类下方:

public class Data : INotifyPropertyChanged
{        
    private string id= string.Empty;
    private string name = string.Empty;
    private string description = string.Empty;


    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public string ID
    {
        get
        {
            return this.id;
        }

        set
        {
            if (value != this.id)
            {
                this.id = value;
                NotifyPropertyChanged("ID");
            }
        }
    }

    public string Name
    {
        get
        {
            return this.name;
        }

        set
        {
            if (value != this.name)
            {
                this.name = value;
                NotifyPropertyChanged("Name");
            }
        }
    }

    public string Description
    {
        get
        {
            return this.description;
        }

        set
        {
            if (value != this.description)
            {
                this.description = value;
                NotifyPropertyChanged("Description");
            }
        }
    }
}

同样在 xaml.cs 中我实现了INotifyPropertyChanged:

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

此外,在上面的 xaml 中,我有一个按钮定义为:

<Button Click="btn_Click"/>

,其实现在 xaml.cs 中,如下所示:

    private void btn_Click(object sender, System.Windows.RoutedEventArgs e)
    {
      (DataContext as MyViewModel).SearchInDb('0303003'); // 0303003 -> this is only an example.
    }

在按钮上单击调用MyViewModel类的方法,然后从该处调用查询到数据库以使用ID = 0303003检索数据。

MyViewModel类(我只显示方法):

 public void SearchInDb(string id)
 {
      // request data to sql server database
      // and then populate a Data Class Object with the data retrieved
      // from database:

      Data = new Data(){                            
                ID = sReader[0].ToString().Trim(),
                Name = sReader[1].ToString().Trim(),
                Description = sReader[2].ToString().Trim()
             };
 }

注意:MyViewModel类不实现INotifyPropertyChanged。

我的问题如下

在上面的方法“SearchInDb”中填充新的Data对象后,网格中的标签不会更新,它们仍为空。

1 个答案:

答案 0 :(得分:1)

您需要设置View的DataContext:

<强> View.xaml.cs

public View()
{
    InitializeComponent();
    this.DataContext = new MyViewModel();
}

但您的代码段中还有其他一些问题。以MVVM方式,ViewModel应该实现INotifyPropertyChanged。不是数据类。

这是应该如何:

数据类

public class Data
{        
    public string Id {get;set;}
    public string Name {get;set;}
    public string Description {get; set;}
}

<强> MyViewModel

public class MyViewModel : INotifyPropertyChanged
{        
    private Data _data;

    public string ID
    {
        get { return _data.Id;}
        set 
        {
            if(_data.Id != value)
            {
                _data.Id = value;
                NotifyPropertyChanged();
            }
        }
    }

    // Same stuff for the other properties

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName]String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public void SearchInDb(string id)
    {
        // request data to sql server database
        // and then populate a Data Class Object with the data retrieved
        // from database:

        _data = new Data()
        {                            
            Id = sReader[0].ToString().Trim(),
            Name = sReader[1].ToString().Trim(),
            Description = sReader[2].ToString().Trim()
        };

        NotifyPropertyChanged(nameof(ID));
        NotifyPropertyChanged(nameof(Name));
        NotifyPropertyChanged(nameof(Description));
    }
}

您的NotifyPropertyChanged代码没有任何问题。这只是一种古老的做法。这种方式更现代,不需要魔术字符串; - )。

您还可以使用视图模型中的Command属性将按钮的Command依赖项属性绑定到SearchInDb方法。这样,您就不需要在代码中编写代码了。但那是另一个问题:D。

并且您的View不需要实现INotifyPropertyChanged(除非您的具体情况需要这样做)。