我想将按钮文本绑定到 LINQ 表达式,如下所示:
public string CloseButtonText => Roles.Any(r => r.IsChanged) ? "Save and close" : "Close";
...但它不起作用。文本在启动时已正确设置,但当任何 RoleViewModel 对象更改时它不会更改。
我就是这样设置的。
public class RoleSelectionViewModel : ViewModelBase
{
public RoleSelectionViewModel()
{
LoadRoles();
}
private readonly ObservableCollection<RoleViewModel> _roles = [];
public IList<RoleViewModel> Roles => _roles;
public string CloseButtonText => Roles.Any(r => r.IsChanged) ? "Save and close" : "Close";
private void LoadRoles()
{
// Prevents crash when trying to read XML roles during design-time.
if (DesignerProperties.GetIsInDesignMode(new System.Windows.DependencyObject()))
{
return;
}
var roles = [ .. RolesManagement.ReadRolesXml().OrderBy(r => r.RoleName), ];
roles.ForEach(r => Roles.Add(new RoleViewModel(r)));
}
// rest of the class...
public class RoleViewModel : ViewModelBase
{
public RoleViewModel() { }
public RoleViewModel(Role role) => Role = role;
public Role Role { get; protected set; }
public int RoleId => Role.RoleId;
public string RoleName => Role.RoleName;
public string Name
{
get { return Role.IssuedBy; }
set
{
Role.IssuedBy = value;
OnPropertyChanged();
}
}
public string Department
{
get { return Role.Department; }
set
{
Role.Department = value;
OnPropertyChanged();
}
}
public string Email
{
get { return Role.Email; }
set
{
Role.Email = value;
OnPropertyChanged();
}
}
// etc...
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool _isChanged = false;
public bool IsChanged
{
get { return _isChanged; }
set
{
_isChanged = value;
OnPropertyChanged();
}
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
if (propertyName != nameof(IsChanged))
{
IsChanged = true;
}
}
}
<Button
x:Name="Close_Button"
Width="96"
Height="30"
Padding="10,0,10,0"
Background="#FF838383"
Foreground="White"
Command="{Binding CloseCommand}"
>
<TextBlock
x:Name="Close_Button_Text"
Text="{Binding CloseButtonText}"
/>
</Button>
我也尝试过手动订阅
RoleViewModel.PropertyChanged
事件,但也没有成功。奇怪的是,当我单击关闭按钮时,Role_PropertyChanged
会触发,但任何角色属性更改时不会触发。
foreach (var role in Roles)
{
role.PropertyChanged += Role_PropertyChanged;
}
private void Role_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(RoleViewModel.IsChanged))
{
this.OnPropertyChanged(nameof(CloseButtonText));
}
}
编辑:我尝试订阅
CollectionChanged
的 ObservableCollection
事件,但没有骰子。 Role_PropertyChanged
方法仅在我实际单击“关闭”按钮时触发;我不知道为什么。
public string CloseButtonText { get; set; } = "Close";
private void LoadRoles()
{
_roles.CollectionChanged += Roles_CollectionChanged;
// rest of the method unchanged
}
private void Roles_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
{
foreach (RoleViewModel item in e.OldItems)
{
item.PropertyChanged -= Role_PropertyChanged;
}
}
if (e.NewItems != null)
{
foreach (RoleViewModel item in e.NewItems)
{
item.PropertyChanged += Role_PropertyChanged;
}
}
}
private void Role_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (sender is RoleViewModel role
&& role.IsChanged
&& e.PropertyName == nameof(RoleViewModel.IsChanged))
{
CloseButtonText = "Save and close";
this.OnPropertyChanged(nameof(CloseButtonText));
}
}
编辑 2:事实证明,您无法像我最初预期的那样绑定到 LINQ 表达式。然而,在每个
UpdateSourceTrigger=PropertyChanged
的绑定上添加 TextBox
后,它就起作用了。默认似乎是在 TextBox
失去焦点后引发事件。所以完整的绑定应该是这样的:Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
。我仍然必须订阅 CollectionChanged
上的 ObservableCollection
事件,并且还订阅每个 RoleViewModel
的 PropertyChanged
事件,如第一次编辑中所述。
事实证明,您无法像我最初的意图那样绑定到 LINQ 表达式。我将属性更改为:
public string CloseButtonText { get; set; } = "Close"
。
我遇到的问题是,该事件没有在我预期的时候(当文本框内容更改时)引发。 然而,在每个
UpdateSourceTrigger=PropertyChanged
的绑定上添加 TextBox
后,它就起作用了。默认似乎是在 TextBox
失去焦点后引发事件。所以完整的绑定应该是这样的:Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
。我仍然必须订阅 CollectionChanged
上的 ObservableCollection
事件,并且还订阅每个 RoleViewModel
的 PropertyChanged
事件,如第一次编辑中所述。