Kal*_*ale 0 c# wpf binding mvvm
我正在尝试使用此示例设置有效的双向更新。
这些是相关的代码片段:
XAML:
<Button Click="clkInit">Initialize</Button>
<Button Click="clkStudent">Add student</Button>
<Button Click="clkChangeStudent">Change students</Button>
(...)
<TabControl Name="tabControl1" ItemsSource="{Binding StudentViewModels}" >
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=StudentFirstName}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Grid>
<Label Content="First Name" Name="label1" />
<TextBox Name="textBoxFirstName" Text="{Binding Path=StudentFirstName}" />
<Label Content="Last Name" Name="label2" />
<TextBox Name="textBoxLastName" Text ="{Binding Path=StudentLastName}" />
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Run Code Online (Sandbox Code Playgroud)
主窗口:
public partial class MainWindow : Window
{
internal MainWindowViewModel myMWVM;
public MainWindow()
{
InitializeComponent();
}
private void clkInit(object sender, RoutedEventArgs e)
{
myMWVM= new MainWindowViewModel();
DataContext = myMWVM;
}
private void clkStudent(object sender, RoutedEventArgs e)
{
myMWVM.StudentViewModels.Add(new StudentViewModel());
}
// For testing - call a function out of the student class to make changes there
private void clkChangeStudent(object sender, RoutedEventArgs e)
{
for (Int32 i = 0; i < test.StudentViewModels.Count; i++)
{
myMWVM.StudentViewModels.ElementAt((int)i).changeStudent();
}
}
}
Run Code Online (Sandbox Code Playgroud)
主要观点:
class MainWindowViewModel : INotifyPropertyChanged
{
ObservableCollection<StudentViewModel> _studentViewModels =
new ObservableCollection<StudentViewModel>();
// Collection for WPF.
public ObservableCollection<StudentViewModel> StudentViewModels
{
get { return _studentViewModels; }
}
// Constructor. Add two stude
public MainWindowViewModel()
{
_studentViewModels.Add(new StudentViewModel());
_studentViewModels.Add(new StudentViewModel());
}
// Property change.
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Run Code Online (Sandbox Code Playgroud)
学生观点:
class StudentViewModel : INotifyPropertyChanged
{
Lazy<Student> _model;
string _studentFirstName;
public string StudentFirstName
{
get { return _studentFirstName; }
set
{
if (_studentFirstName != value)
{
_studentFirstName = value;
_model.Value.StudentFirstName = value;
OnPropertyChanged("StudentFirstName");
}
}
}
string _studentLastName;
public string StudentLastName
{
get { return _studentLastName; }
set
{
if (_studentLastName != value)
{
_studentLastName = value;
_model.Value.StudentLastName = value;
OnPropertyChanged("StudentLastName");
}
}
}
public void changeStudent()
{
_model.Value.changeStudent();
}
public StudentViewModel()
{
_studentFirstName = "Default";
_model = new Lazy<Student>(() => new Student());
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Run Code Online (Sandbox Code Playgroud)
学生:
class Student
{
public string StudentFirstName { get; set; }
public string StudentLastName { get; set; }
public Student()
{
MessageBox.Show("Student constructor called");
}
public Student(string nm)
{
StudentLastName = nm;
}
public void changeStudent()
{
StudentLastName = "McDonald";
}
}
Run Code Online (Sandbox Code Playgroud)
如果您读到这里,我已经感谢您 :) 尽管如此,通过调用“clkChangeStudent”,我没有看到文本框中的更改。我猜是因为我没有调用StudentViewModel 的set-method。我正在做的项目有点复杂,很多事情发生在班级(这里是学生)本身。
如何通过学生类本身的设置值获取文本框更新?
您的实际代码显然不会通知界面的更改。原因很简单。您更改学生姓名的方法位于 Student 模型中,并且该模型未实现 INotifyPropertyChanged。
根据一个问题,有两种解决方案可以解决此问题,changeStudent() 方法是否必须坚持对象模型,也就是说,您的要求是否允许您将 changeStudent() 方法移动到视图模型?
如果是,那么,第一个解决方案,只需从模型中删除 changeStudent 方法并将其移动到视图模型,如下所示:
class StudentViewModel : INotifyPropertyChanged
{
...
public void changeStudent()
{
this.StudentLastName = "McDonald";
}
}
Run Code Online (Sandbox Code Playgroud)
在另一种情况下,第二种解决方案,您必须在模型属性更改时引发事件,然后让您的视图模型订阅这些更改。您可以在模型中像这样继续:
class Student : INotifyPropertyChanged
{
...
private string studentLastName;
public string StudentLastName
{
get
{
return this.studentLastName;
}
set
{
if(this.studentLastname != value)
{
this.studentLastName = value;
this.OnPropertyChanged("StudentLastName");
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于视图模型:
class StudentViewModel : INotifyPropertyChanged
{
...
public StudentViewModel(Student model)
{
this._model = model;
this._model.PropertyChanged += (sender, e) =>
{
if(e.PropertyName == "StudentLastName")
{
this.OnPropertyChanged("StudentLastName");
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
两种解决方案都有效。真正重要的是,您了解您的代码在值更改时明确需要通知接口。
| 归档时间: |
|
| 查看次数: |
6682 次 |
| 最近记录: |