此转换器是我的间接问题,或者特别是其中的ObservableCollection user_modules。此转换器连接到一组按钮。
当我的应用程序启动时,集合为空,所有按钮都被禁用,然后在用户登录时填充它。但是,视图和视图模型不会通知集合已更改,按钮在不应该被禁用时保持禁用状态。我该怎么做?
我相信以下三段代码都没问题,但我不确定第四段,我相信这是我需要做的改动。
public class IsEnabledMultiValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
bool userHasAccess = false;
int Module_ID = (int)values[0];
ObservableCollection<UserModuleLevel> user_module_levels = values[1] as ObservableCollection<UserModuleLevel>;
UserModuleLevel userModuleLevel = user_module_levels.SingleOrDefault(um => um.Module_ID == Module_ID);
if (userModuleLevel != null)
{
userHasAccess = true;
}
return (userHasAccess);
}
catch
{
return false;
}
}
我的XAML:
<Button.IsEnabled>
<MultiBinding Converter="{StaticResource converter}" >
<Binding Path="Module_ID" />
<Binding Path="DataContext.UserModuleCollection"
RelativeSource="{RelativeSource AncestorType=Window}" />
</MultiBinding>
</Button.IsEnabled>
我的ViewModel:一旦用户登录UserModuleLevels,就会填充_current_user。
public ObservableCollection<UserModuleLevel> UserModuleCollection
{
get { return CurrentUser._current_user.UserModuleLevels; }
}
保存集合的用户类:
public class User
{
public User(){}
public int User_ID { get; set; }
public string Name { get; set; }
public ObservableCollection<UserModuleLevel> UserModuleLevels = new ObservableCollection<UserModuleLevel>();
}
答案 0 :(得分:1)
我不确定你要在这里实现什么,但我能得到的是你想要在列表中添加或删除项目时调用转换器。
如果是这种情况,你可以在MultiBinding下的XAML中有另一个绑定,它将绑定到ObservableCollection的Count
。每当添加/删除项目时,Count
都会更新。所以,你可以这样做只是为了得到通知。
<Button.IsEnabled>
<MultiBinding Converter="{StaticResource converter}" >
<Binding Path="Module_ID" />
<Binding Path="DataContext.UserModuleCollection"
RelativeSource="{RelativeSource AncestorType=Window}" />
<Binding Path="DataContext.UserModuleCollection.Count" <-- Only to refresh
RelativeSource="{RelativeSource AncestorType=Window}" />
</MultiBinding>
</Button.IsEnabled>
答案 1 :(得分:0)
填充observable集合时,不会执行转换器的Convert
方法。这是因为只有ListBox
或ComboBox
之类的ItemsControl会监听CollectionChanged
接口的INotifyCollectionChanged
事件。但这不适用于你的问题。
如果我正确理解您的代码,我建议您创建一个为每个按钮实例化的新ViewModel类。在其中,您可以指定模块ID以及用户是否可以使用它(您当前在转换器中执行的检查)。将每个按钮绑定到该视图模型的新实例。
我希望这会有所帮助。如果您有任何疑问,请发表评论。
答案 2 :(得分:0)
可能的原因有两点突出。你说当用户登录模块级别时会填充? 那么最初的CurrentUser和后续模块级别将为null? 在设置Currentuser及其UserModuleLevels时,您可能需要引发通知事件。
此外,在第四部分中,您将私有变量设置为新变量,但该属性也有一个setter,没有通知事件。如果您随后设置该属性,则需要实现INotifyPropertyChanged。或者通过删除setter使其成为只读。
public class User:INotifyPropertyChanged
{
public User(){}
public int User_ID { get; set; }
public string Name { get; set; }
private ObservableCollection<UserModuleLevel> user_module_levels = new ObservableCollection<UserModuleLevel>();
public ObservableCollection<UserModuleLevel> UserModuleLevels
{
get
{ return user_module_levels; }
set
{
user_module_levels = value;
this.OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}