WPF:绑定 属性 到 TextBlock 不起作用
WPF: Bind property to TextBlock not working
我有以下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>
数据下方Class:
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 class 上的方法,并从那里调用对数据库的查询以使用 ID = 0303003 检索数据。
下面MyViewModel class(我只展示方法):
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 class 未实现 INotifyPropertyChanged。
我的问题如下:
在上述方法中填充新的数据对象后 "SearchInDb",我在网格中的标签没有更新,它们仍然是空的。
您需要设置视图的 DataContext:
View.xaml.cs
public View()
{
InitializeComponent();
this.DataContext = new MyViewModel();
}
但是您的代码片段中还有一些其他问题。在 MVVM
方式中,应该实现 INotifyPropertyChanged
的是 ViewModel
。不是数据 class.
它应该是这样的:
数据Class
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
依赖项 属性 绑定到 SearchInDb
方法。这样,你就不需要在你的代码后面写代码了。但那是另一个问题 :D.
并且您的视图不需要实现 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>
数据下方Class:
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 class 上的方法,并从那里调用对数据库的查询以使用 ID = 0303003 检索数据。
下面MyViewModel class(我只展示方法):
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 class 未实现 INotifyPropertyChanged。
我的问题如下:
在上述方法中填充新的数据对象后 "SearchInDb",我在网格中的标签没有更新,它们仍然是空的。
您需要设置视图的 DataContext:
View.xaml.cs
public View()
{
InitializeComponent();
this.DataContext = new MyViewModel();
}
但是您的代码片段中还有一些其他问题。在 MVVM
方式中,应该实现 INotifyPropertyChanged
的是 ViewModel
。不是数据 class.
它应该是这样的:
数据Class
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
依赖项 属性 绑定到 SearchInDb
方法。这样,你就不需要在你的代码后面写代码了。但那是另一个问题 :D.
并且您的视图不需要实现 INotifyPropertyChanged(除非您的情况特别需要)。