gpt4 book ai didi

c# - 如何结合两个 ObservableCollection 来绑定(bind)动态按钮

转载 作者:行者123 更新时间:2023-12-03 10:59:35 25 4
gpt4 key购买 nike

这是使用 C# 和 MVVM。

目前,我有一堆按钮通过绑定(bind)一个名为 ModuleCollection 的 ObservableCollection 创建到面板上。

模块定义为:

public string ModuleName { get; private set; }
public string ModuleAbbreviation { get; private set; }
public bool ModuleDisabled { get; private set; }
public DateTime ModuleLicenseDate { get; private set; }

每个按钮下方的标签设置为 ModuleName,并且按钮的 Content 属性设置为 ModuleAbbreviation。

我还有一个 current_user 对象,它包含一个名为 UserModules 的 ObservableCollection
一个 UserModule 被定义为:
public int Module_ID { get; set; }
public int User_Module_Access { get; set; }

使用 ModuleCollection 和 current_user.UserModules 列表,我想在以下场景下启用按钮:
  • 如果 Module.Disabled = false
  • 和 Module.ModuleLicenseDate > Now()
  • 和 UserModule.User_Module_Access > 0

  • 否则按钮将被禁用。

    其他需要注意的事项:UserModules 可能只有 ModuleCollection 的一个子集,并且 ModuleCollection 将是静态的,但 UserModules 中的属性会不时刷新。

    我的问题是:如何绑定(bind)这两个集合,以便它们可以创建我的按钮并基于两者设置 IsEnabled 属性?

    [编辑] 2013-12-07
    <Button.IsEnabled>
    <MultiBinding Converter="{Binding viewmodel:IsEnabledMultiValueConverter}">
    <Binding Source="{Binding ModuleID}" />
    <Binding Source="{Binding ModuleDisabled}" />
    <Binding Source="{Binding ModuleLicenseDate}" />
    <Binding Source="{Binding current_user.user_modules}" />
    </MultiBinding>
    </Button.IsEnabled>

    [EDIT2] 2013-12-09

    当我更改用户模块中的模块访问级别时,该事件被触发。我将值从可访问(1)更改为不可访问(0),因此该按钮应该被禁用,但这不会发生。
    public class UserModule : INotifyPropertyChanged
    {
    public UserModule(int Module_ID, int User_Module_Access)
    {
    this.Module_ID = Module_ID;
    this.User_Module_Access = User_Module_Access;
    }

    private int _userModuleAccess;

    public int Module_ID { get; set; }

    public int User_Module_Access
    {
    get { return _userModuleAccess; }
    set
    {
    _userModuleAccess = value;
    MessageBox.Show("User_Module_Access");
    RaisePropertyChanged("User_Module_Access");
    }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
    if (PropertyChanged != null)
    PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));

    }
    }

    我的想法是,当项目属性更改时,需要发生 ObservableCollection 的事件。我读过 ObservableCollections 不会这样做,只会添加、删除和移动项目。这该怎么做?

    User 类中的一些方法?
    public class User
    {
    public string UserName { get; set; }
    public ObservableCollection<UserModule> UserModules = new ObservableCollection<UserModule>();
    }

    [Edit3] 2013-12-10 重做 - 实现 ItemsObservableObservableCollection
    启动器.XAML
    <Button Content="{Binding ModuleAbbreviation}" 
    Style="{DynamicResource LauncherButton}"
    Background="{Binding ModuleColor}"
    FontSize="32" FontFamily="Tahoma" Width="130" Height="100"
    Command="{Binding DataContext.LaunchCommand, RelativeSource={RelativeSource AncestorType=Window}}"
    CommandParameter="{Binding ModuleName}">
    <Button.Resources>
    <viewmodel:IsEnabledMultiValueConverter x:Key="converter" />
    </Button.Resources>
    <Button.IsEnabled>
    <MultiBinding Converter="{StaticResource converter}">
    <Binding Path="ModuleID" />
    <Binding Path="ModuleEnabled" />
    <Binding Path="ModuleLicenseDate" />
    <Binding ElementName="gridModules" Path="DataContext.CurrentUser" />
    </MultiBinding>
    </Button.IsEnabled>
    </Button>

    LauncherViewModel.cs
    class LauncherViewModel
    {
    public LauncherViewModel()
    {
    timer = new Timer(SetModuleAccess, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
    }
    int pass = 0;
    bool _isEnabled = false;
    Timer timer;
    private void SetModuleAccess(object state)
    {
    if (pass > 0)
    {
    if (_isEnabled)
    _isEnabled = false;
    else
    _isEnabled = true;

    foreach (Users.UserModule uModule in ups.model.ups_repository._current_user.UserModules)
    {
    if (uModule.Module_ID == 0)
    {
    if (_isEnabled == false)
    uModule.User_Module_Access = 0;
    else
    uModule.User_Module_Access = 1;
    }
    }
    if (pass == 2)
    ups.model.ups_repository._current_user.UserModules.Add(new Users.UserModule(8, 1));
    }
    pass++;
    }

    public Users.User CurrentUser
    {
    get { return ups.model.ups_repository._current_user; }
    }

    public ObservableCollection<Module> ModuleCollection
    {
    get { return ModuleKey._module_objects; }
    }
    }
    public class IsEnabledMultiValueConverter : IMultiValueConverter
    {
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    try
    {
    bool userHasAccess = false;
    int ModuleID = (int)values[0];
    bool ModuleEnabled = (bool)values[1];
    string ModuleLicenseDate = (string)values[2];

    Users.User user = values[3] as Users.User;
    Users.UserModule userModule = user.UserModules.SingleOrDefault(um => um.Module_ID == ModuleID);

    DateTimeFormatInfo dtfi = new DateTimeFormatInfo();
    dtfi.ShortDatePattern = "yyyy-MM-dd";
    dtfi.DateSeparator = "-";
    DateTime MLicenseDate = System.Convert.ToDateTime(ModuleLicenseDate, dtfi);

    if (userModule != null)
    {
    userHasAccess = userModule.User_Module_Access > 0;
    }
    return (ModuleEnabled && (MLicenseDate >= DateTime.Now) && userHasAccess);
    }
    catch
    {
    return false;
    }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
    throw new NotImplementedException();
    }
    }

    用户.cs
    public class User : INotifyPropertyChanged
    {
    public static User CreateNewUser()
    {
    return new User();
    }

    public User() {}

    public int User_ID { get; set; }
    public string Username { get; set; }
    public string Name { get; set; }
    public string Job_Title { get; set; }
    public string Department { get; set; }
    public string Company { get; set; }
    public string Phone_Office { get; set; }
    public string Phone_Mobile { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public DateTime Last_Login { get; set; }
    public int Status { get; set; }
    public int Session_Timeout { get; set; }

    private ItemsObservableObservableCollection<UserModule> user_modules = new ItemsObservableObservableCollection<UserModule>();

    public ItemsObservableObservableCollection<UserModule> UserModules
    {
    get
    {
    return user_modules;
    }
    set
    {
    user_modules = value;
    }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
    if (PropertyChanged != null)
    PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));

    }
    }

    用户模块.cs
    public class UserModule : INotifyPropertyChanged
    {
    public UserModule(int Module_ID)
    {
    this.Module_ID = Module_ID;
    }

    public UserModule(int Module_ID, int User_Module_Access)
    {
    this.Module_ID = Module_ID;
    this.User_Module_Access = User_Module_Access;
    }

    private int _module_id;
    private int _userModuleAccess;

    public int Module_ID
    {
    get { return _module_id; }
    set
    {
    _module_id = value;
    RaisePropertyChanged("Module_ID");
    }
    }

    public int User_Module_Access
    {
    get { return _userModuleAccess; }
    set
    {
    _userModuleAccess = value;
    RaisePropertyChanged("User_Module_Access");
    }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
    if (PropertyChanged != null)
    PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));

    }
    }

    ups.cs
    namespace ups.model
    {
    public static class ups_repository
    {
    public static Users.User _current_user = new Users.User();

    public static void LoadUser(string Username, string Key, string Message)
    {
    ...
    }
    }
    }

    此时按钮正在显示,在上面的 VM 中,我将集合中的第一个用户模块从启用切换到禁用,每五秒钟。我还为集合中的最后一个添加了权限。按钮未启用并禁用它们应有的方式。

    最佳答案

    您可以在 Button 的 IsEnabled 属性上尝试使用 MultiValueConverter 进行 MultiBinding。 MultiValueConverter 会将 Module 绑定(bind)到 Button;和当前用户的模块集合(在下面的示例中,我发送了用户本身)并进行测试以返回一个 bool 值以指示按钮是否可以启用或禁用。

    <Window x:Class="WpfHowTo.ItemsControlTestHorn"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:WpfHowTo"
    Title="ItemsControlTestHorn" Height="300" Width="300">
    <Window.Resources>
    <l:MultiValueConverter x:Key="multiValueConverter"/>
    </Window.Resources>
    <Grid Name="gridModules">
    <ItemsControl ItemsSource="{Binding Path=Modules}">
    <ItemsControl.ItemTemplate>
    <DataTemplate>
    <StackPanel>
    <Button Content="{Binding ModuleAbbreviation}">
    <Button.IsEnabled>
    <MultiBinding Converter="{StaticResource multiValueConverter}">
    <Binding Path="."/>
    <Binding ElementName="gridModules" Path="DataContext.CurrentUser"/>
    <!--<Binding RelativeSource="{RelativeSource AncestorType=Grid}" Path="DataContext.CurrentUser"/>-->
    </MultiBinding>
    </Button.IsEnabled>
    </Button>
    </StackPanel>
    </DataTemplate>
    </ItemsControl.ItemTemplate>
    </ItemsControl>
    </Grid>
    </Window>

    MultiValueConverter 是这样的。
    public class MultiValueConverter : IMultiValueConverter
    {

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    bool result = true;

    Module module = values[0] as Module;
    User user = values[1] as User;
    bool userHasAccess = false;

    UserModule userModule = user.UserModules.SingleOrDefault(um => um.Module_ID == module.Module_ID);

    if (userModule != null)
    {
    userHasAccess = userModule.User_Module_Access == 1;
    }

    return result = ! module.ModuleDisabled && module.ModuleLicenseDate > DateTime.Now && userHasAccess;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
    throw new NotImplementedException();
    }
    }

    类定义
    public class Module
    {
    public int Module_ID { get; set; }
    public string ModuleName { get; set; }
    public string ModuleAbbreviation { get; set; }
    public bool ModuleDisabled { get; set; }
    public DateTime ModuleLicenseDate { get; set; }
    }

    public class UserModule
    {
    public int Module_ID { get; set; }
    public int User_Module_Access { get; set; }
    }

    public class User
    {
    private ObservableCollection<UserModule> _userModules = new ObservableCollection<UserModule>();
    public string UserName { get; set; }

    public ObservableCollection<UserModule> UserModules
    {
    get
    {
    return _userModules;
    }
    }
    }

    关于c# - 如何结合两个 ObservableCollection 来绑定(bind)动态按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20379800/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com