Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to combine two ObservableCollection to bind dynamic buttons
    primarykey
    data
    text
    <p>This is using C# and MVVM.</p> <p>At the moment I have a bunch of buttons that are created on to a panel via binding an ObservableCollection&lt;Module&gt; called ModuleCollection.</p> <p>module is defined as:</p> <pre><code>public string ModuleName { get; private set; } public string ModuleAbbreviation { get; private set; } public bool ModuleDisabled { get; private set; } public DateTime ModuleLicenseDate { get; private set; } </code></pre> <p>A label below each button gets set to ModuleName and the Content property of the button gets set to ModuleAbbreviation.</p> <p>I also have a current_user object that holds a ObservableCollection&lt;UserModule&gt; called UserModules A UserModule is defined as:</p> <pre><code>public int Module_ID { get; set; } public int User_Module_Access { get; set; } </code></pre> <p>Using the ModuleCollection and current_user.UserModules lists, I would like to enable the buttons under the follow scenarios:</p> <ul> <li>If the Module.Disabled = false </li> <li>and the Module.ModuleLicenseDate &gt; Now() </li> <li>and the UserModule.User_Module_Access &gt; 0</li> </ul> <p>Otherwise the button will be disabled.</p> <p>Other things to note: is that UserModules may only have a subset of ModuleCollection and ModuleCollection will be static but the properties within UserModules will be refreshed from time to time.</p> <p>My question is: How to I go about binding these two collections so that I can them create my buttons and set the IsEnabled property based on both?</p> <p><strong>[EDIT] 2013-12-07</strong></p> <pre><code>&lt;Button.IsEnabled&gt; &lt;MultiBinding Converter="{Binding viewmodel:IsEnabledMultiValueConverter}"&gt; &lt;Binding Source="{Binding ModuleID}" /&gt; &lt;Binding Source="{Binding ModuleDisabled}" /&gt; &lt;Binding Source="{Binding ModuleLicenseDate}" /&gt; &lt;Binding Source="{Binding current_user.user_modules}" /&gt; &lt;/MultiBinding&gt; &lt;/Button.IsEnabled&gt; </code></pre> <p><strong>[EDIT2] 2013-12-09</strong></p> <p>When I change the module access level in a user module the event is getting fired. I change the value from accessible(1) to unaccessible(0), so in-turn the button should get disabled, however this does not happen.</p> <pre><code>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)); } } </code></pre> <p>My thoughts are, that an event for ObservableCollection&lt;UserModule&gt; needs to occur when an item property changes. I have read that ObservableCollections don't do this, only adding, deleting and moving items. How to do this?</p> <p>Some how in the User class?</p> <pre><code>public class User { public string UserName { get; set; } public ObservableCollection&lt;UserModule&gt; UserModules = new ObservableCollection&lt;UserModule&gt;(); } </code></pre> <p><br/> <strong>[Edit3] 2013-12-10 Redo - Implementing ItemsObservableObservableCollection</strong><br/> Launcher.XAML</p> <pre><code>&lt;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}"&gt; &lt;Button.Resources&gt; &lt;viewmodel:IsEnabledMultiValueConverter x:Key="converter" /&gt; &lt;/Button.Resources&gt; &lt;Button.IsEnabled&gt; &lt;MultiBinding Converter="{StaticResource converter}"&gt; &lt;Binding Path="ModuleID" /&gt; &lt;Binding Path="ModuleEnabled" /&gt; &lt;Binding Path="ModuleLicenseDate" /&gt; &lt;Binding ElementName="gridModules" Path="DataContext.CurrentUser" /&gt; &lt;/MultiBinding&gt; &lt;/Button.IsEnabled&gt; &lt;/Button&gt; </code></pre> <p>LauncherViewModel.cs</p> <pre><code>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 &gt; 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&lt;Module&gt; 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 =&gt; 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 &gt; 0; } return (ModuleEnabled &amp;&amp; (MLicenseDate &gt;= DateTime.Now) &amp;&amp; userHasAccess); } catch { return false; } } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } </code></pre> <p>User.cs</p> <pre><code>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&lt;UserModule&gt; user_modules = new ItemsObservableObservableCollection&lt;UserModule&gt;(); public ItemsObservableObservableCollection&lt;UserModule&gt; 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)); } } </code></pre> <p>UserModule.cs</p> <pre><code>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)); } } </code></pre> <p>ups.cs</p> <pre><code>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) { ... } } } </code></pre> <p>At this point buttons are displaying, in the VM above I switch the first user module in the collection from enabled to disabled, each five seconds. I also add permission for the last in the collection. The buttons are not enabled and disabling the way they should.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload