Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 以某种方式通知转换器集合已更改_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# 以某种方式通知转换器集合已更改

C# 以某种方式通知转换器集合已更改,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,这个转换器是我的间接问题,或者特别是其中的ObservableCollection用户_模块。此转换器连接到一组按钮 当我的应用程序启动时,集合为空,所有按钮均被禁用,然后当用户登录时,将填充该集合。但是,不会通知视图和viewmodel集合已更改,按钮在不应更改时仍处于禁用状态。我该怎么做 我相信下面三段代码是可以的,但我不确定第四段,我相信这是我需要修改的地方 public class IsEnabledMultiValueConverter : IMultiValueConverter {

这个转换器是我的间接问题,或者特别是其中的ObservableCollection用户_模块。此转换器连接到一组按钮

当我的应用程序启动时,集合为空,所有按钮均被禁用,然后当用户登录时,将填充该集合。但是,不会通知视图和viewmodel集合已更改,按钮在不应更改时仍处于禁用状态。我该怎么做

我相信下面三段代码是可以的,但我不确定第四段,我相信这是我需要修改的地方

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;
        }
    }
公共类IsEnabledMultiValueConverter:IMMultivalueConverter
{
公共对象转换(对象[]值,类型targetType,对象参数,System.Globalization.CultureInfo区域性)
{
尝试
{
bool userHasAccess=false;
int模块_ID=(int)值[0];
ObservableCollection用户\模块\级别=值[1]作为ObservableCollection;
UserModuleLevel UserModuleLevel=user\u module\u levels.SingleOrDefault(um=>um.module\u ID==module\u ID);
if(userModuleLevel!=null)
{
userHasAccess=true;
}
返回(userHasAccess);
}
抓住
{
返回false;
}
}
我的XAML:

<Button.IsEnabled>
    <MultiBinding Converter="{StaticResource converter}" >
       <Binding Path="Module_ID" />
       <Binding Path="DataContext.UserModuleCollection"
                RelativeSource="{RelativeSource AncestorType=Window}" />
    </MultiBinding>
</Button.IsEnabled>

My ViewModel:一旦用户登录UserModuleLevel并填充_current_user

public ObservableCollection<UserModuleLevel> UserModuleCollection
{
    get { return CurrentUser._current_user.UserModuleLevels; }
}
公共ObservableCollection用户模块Collection
{
获取{return CurrentUser.\u current\u 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>();
}
公共类用户
{
公共用户(){}
公共int用户_ID{get;set;}
公共字符串名称{get;set;}
public ObservableCollection UserModuleLevel=新ObservableCollection();
}

填充可观察集合时,转换器的
Convert
方法将不会执行。这是因为只有项控件,如
ListBox
ComboBox
侦听
INotifyCollectionChanged
接口的
CollectionChanged
事件。但这不适用于为你解决这个问题

如果我正确理解了您的代码,我建议您创建一个新的ViewModel类,该类将为每个按钮实例化。在该类中,您指定模块ID以及用户是否能够使用它(您当前在转换器中执行的检查)。将每个按钮绑定到该视图模型的新实例


我希望这会有所帮助。如果您有任何问题,请留下评论。

有两点可能是原因。您说用户何时登录ModuleLevel? 那么最初CurrentUser和后续模块级别将为空? 设置Currentuser及其UserModuleLevel时,可能需要引发通知事件

此外,在第四节中,您将th private变量设置为new,但该属性也有一个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));
                    }
                }

        }
公共类用户:INotifyPropertyChanged
{
公共用户(){}
公共int用户_ID{get;set;}
公共字符串名称{get;set;}
私有ObservableCollection用户\模块\级别=新ObservableCollection();
公共ObservableCollection用户模块级别
{
得到
{返回用户\模块\级别;}
设置
{ 
用户\模块\级别=值;
this.OnPropertyChanged();
}
}
公共事件属性更改事件处理程序属性更改;
[NotifyPropertyChangedInvocator]
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChangedEventHandler处理程序=PropertyChanged;
if(处理程序!=null)
{
处理程序(这是新的PropertyChangedEventArgs(propertyName));
}
}
}

我不确定您想在这里实现什么,但我能得到的是,您希望在列表中添加或删除项目时调用转换器

如果是这种情况,您可以在多重绑定下在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>


您没有以适当的方式使用转换器。您要做的是使用
CanExecute
方法在按钮上设置
命令。