我正在尝试实现WPF表单(显示员工数据),以便在任何字段中进行更改时,头部标签(FullnameTitle)都带有星号。例如。约翰·史密斯*
我使用的是MVVM,它的ViewModel库还可以跟踪更改。我还选择了将模型属性分开(即NotifyPropertyChanged在ViewModel中)
以下是我目前所拥有的。我知道要更新标题标签,我需要在所有表单字段上调用from sqlalchemy.sql import text
session = ...
insert_qry = """
INSERT INTO test (id, name) VALUES(:id1, :name1), (:id2, :name2)
ON DUPLICATE KEY UPDATE id=VALUES(id), name=VALUES(name)
"""
params = {'id1':1, 'name1': 'John', 'id2':2, 'name2': 'Bill'}
session.execute(text(insert_qry), params)
。
我的问题是,有没有一种更好的方法,不需要在每个字段都调用它? (我的完整员工表格有50多个字段)
Window XAML
NotifyPropertyChanged("FullnameTitle")
ViewModel
<Label x:Name="HeadLabel" Content="{Binding FullnameTitle, FallbackValue='Employee Details'}" FontSize="28"/>
<StackPanel>
<Label Content="Employee ID"/>
<TextBox IsEnabled="False" Text="{Binding Employee.EmployeeId}"/>
<Label Content="First name"/>
<TextBox Text="{Binding Firstname, TargetNullValue=''}"/>
<Label Content="Surname"/>
<TextBox Text="{Binding Surname, TargetNullValue=''}"/>
<Label Content="DOB"/>
<DatePicker SelectedDate="{Binding Dob, TargetNullValue=''}"/>
<Label Content="Age"/>
<TextBox Text="{Binding Age, Mode=OneWay}" IsReadOnly="True"/>
</StackPanel>
ViewModelBase
class EmployeeViewModel : ViewModelBase
{
public EmployeeModel Employee { get; set; }
public string FullnameTitle
{
get
{
return string.Format("{0} {1}{2}", Employee.Firstname, Employee.Surname, IsDirty ? "*" : "");
}
}
public string Firstname
{
get
{
return Employee.Firstname;
}
set
{
Employee.Firstname = ApplyPropertyChange(Employee.Firstname, value, "Firstname");
}
}
public string Surname
{
get
{
return Employee.Surname;
}
set
{
Employee.Surname = ApplyPropertyChange(Employee.Surname, value, "Surname");
}
}
public DateTime? Dob
{
get
{
return Employee.Dob;
}
set
{
Employee.Dob = ApplyPropertyChange(Employee.Dob, value, "Dob");
NotifyPropertyChanged("Age");
}
}
public int Age
{
get
{
return Employee.Age; // Age calculation done in EmployeeModel
}
}
}
答案 0 :(得分:-1)
使用事件。
在您的视图模型中,订阅PropertyChanged
:
EmployeeViewModel.cs
class EmployeeViewModel : ViewModelBase
{
public EmployeeViewModel()
{
this.PropertyChanged += (s, e) => NotifyPropertyChanged(nameof(this.FullnameTitle));
}
...
}
但是要小心。调用PropertyChanged
事件发起者NotifyPropertyChanged
的属性是
本身引发PropertyChanged
事件将导致无限递归。
使用由IMultiValueConverter
触发的多重绑定ViewModelBase.IsDirty
:
IsDirtyToStringConverter.cs
class IsDirtyToStringConverter : IMultiValueConverter
{
#region Implementation of IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] is EmployeeViewModel viewModel && values[1] is bool modelIsDirty)
{
return string.Format("{0} {1}{2}",
viewModel.Firstname,
viewModel.Surname,
modelIsDirty
? "*"
: string.Empty);
}
return Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
#endregion
}
Window.xaml
<Window.Resources>
<IsDirtyToStringConverter x:Keyy="IsDirtyToStringConverter" />
</Window.Resources>
<TextBlock x:Name="HeadLabel" FallbackValue='Employee Details'}" FontSize="28" >
<TextBlock.Text>
<MultiBinding Converter="{StaticResource IsDirtyToStringConverter}"
FallbackValue='Employee Details'>
<Binding Path="." />
<Binding Path="IsDirty" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<StackPanel>
<Label Content="Employee ID"/>
<TextBox IsEnabled="False" Text="{Binding Employee.EmployeeId}"/>
<Label Content="First name"/>
<TextBox Text="{Binding Firstname}"/>
<Label Content="Surname"/>
<TextBox Text="{Binding Surname}"/>
<Label Content="DOB"/>
<DatePicker SelectedDate="{Binding Dob}"/>
<Label Content="Age"/>
<TextBlock Text="{Binding Age}" />
</StackPanel>