Introduction
There might be some scenarios in which a user should not be able to select items in a ComboBox. For example, I have year and month ComboBoxes and if I select the current year, I should not be able to select future months for this year. But when I select previous years, I should be able to select any month.
MainPage.xaml:
The Silverlight ComboBoxItem has an IsEnabled property which we can set to true or false based on our requirements. Add the code shown below in the Resources.
<StyleTargetType="ComboBoxItem">
<Setter Property="IsEnabled" Value="{BindingIsActive}"/>
</Style>
IsActive is a property which I am going to add for the items collection.
Complete XAML code:
<UserControl x:Class="ComboBoxInactiveItems.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
xmlns:vm="clr-namespace:ComboBoxInactiveItems">
<UserControl.Resources>
<vm:ViewModel x:Key="ViewModel"/>
<StyleTargetType="ComboBoxItem">
<Setter Property="IsEnabled" Value="{BindingIsActive}"/>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White"DataContext="{Binding Source={StaticResourceViewModel}}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="cmbYear"SelectionChanged="cmbYear_SelectionChanged"ItemsSource="{Binding Year
"Grid.Row="0"Grid.Column="0" Width="100"HorizontalAlignment="Center"/>
<ComboBox x:Name="cmbMonth"ItemsSource="{Binding Month
"DisplayMemberPath="MonthName"Grid.Row="0"Grid.Column="1" Width="100"/>
</Grid>
</UserControl>
ViewModel
In the ViewModel, I added a ViewModelBase which has a NotifyPropertyChanged event. I added a month class which inherits from ViewModelBase. I have 3 properties inside the Month class.
- MonthName(string)
- MonthValue(int)
- IsActive(bool)
public class Month : ViewModelBase
{
privateboolm_IsActive;
public Month()
{
IsActive = true;
}
public string MonthName
{
get;
set;
}
public int MonthValue
{
get;
set;
}
public bool IsActive
{
get;
{
returnm_IsActive;
}
set
{
m_IsActive = value;
NotifyPropertyChanged("IsActive");
}
}
}
In the ViewModel class I have a property which is a type of List<Month>.
public class ViewModel
{
private List<Month>m_Month;
private List<int>m_Year;
public List<Month> Month
{
get;
{
if (m_Month == null)
{
m_Month = newList<Month>()
{
new Month{MonthName="January",MonthValue=1},
new Month{MonthName="February",MonthValue=2},
new Month{MonthName="March",MonthValue=3},
new Month{MonthName="April",MonthValue=4},
new Month{MonthName="May",MonthValue=5},
new Month{MonthName="June",MonthValue=6},
new Month{MonthName="July",MonthValue=7},
new Month{MonthName="August",MonthValue=8},
new Month{MonthName="September",MonthValue=9},
new Month{MonthName="October",MonthValue=10},
new Month{MonthName="November",MonthValue=11},
new Month{MonthName="December",MonthValue=12}
};
}
return m_Month;
}
}
}
Complete ViewModel.cs code:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.Generic;
namespace ComboBoxInactiveItems
{
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class ViewModel
{
private List<Month> m_Month;
private List<int> m_Year;
public List<Month> Month
{
get
{
if (m_Month == null)
{
m_Month = new List<Month>()
{
new Month{MonthName="January",MonthValue=1},
new Month{MonthName="February",MonthValue=2},
new Month{MonthName="March",MonthValue=3},
new Month{MonthName="April",MonthValue=4},
new Month{MonthName="May",MonthValue=5},
new Month{MonthName="June",MonthValue=6},
new Month{MonthName="July",MonthValue=7},
new Month{MonthName="August",MonthValue=8},
new Month{MonthName="September",MonthValue=9},
new Month{MonthName="October",MonthValue=10},
new Month{MonthName="November",MonthValue=11},
new Month{MonthName="December",MonthValue=12}
};
}
return m_Month;
}
}
public List<int> Year
{
get
{
int YearStart = (DateTime.Today.Year) - 5;
int YearEnd = (DateTime.Today.Year);
m_Year = new List<int>();
while (YearStart <= YearEnd)
{
m_Year.Add(YearStart);
YearStart = YearStart + 1;
}
return m_Year;
}
}
}
public class Month : ViewModelBase
{
private bool m_IsActive;
public Month()
{
IsActive = true;
}
public string MonthName { get; set; }
public int MonthValue { get; set; }
public bool IsActive
{
get
{
return m_IsActive;
}
set
{
m_IsActive = value;
NotifyPropertyChanged("IsActive");
}
}
}
}
How it works:
Now based on the selection of year in the ComboBox, I have to set the IsActive property to true or false, which will enable/disable items in a ComboBox. Remember we have already bound this IsActive property with the IsEnabled property in ComboBoxItemstyle.So in my Year ComboBox selection changed event, I am writing the below code which will enable and disable items.
private void cmbYear_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Validating whether user selected current year
if (Convert.ToInt32(cmbYear.SelectedValue) == DateTime.Today.Year)
{
foreach (ComboBoxInactiveItems.Month item incmbMonth.Items)
{
//Finding future months
if (item.MonthValue>= DateTime.Today.Month)
{
//Disabling future months by setting IsActive to false
item.IsActive = false;
/*Incase if the month has been selected previously but disabled now,
* then clearing the selection in the month combobox*/
if (item == cmbMonth.SelectedItem)
cmbMonth.SelectedIndex = -1;
}
}
}
else
{
//Enabling months
foreach (Month item in ((cmbMonth.Items)))
{
item.IsActive = true;
}
}
}
You can also set the IsActive property in ViewModel; it depends on your need. You can modify the above code for your application and can disable ComboBox items. I have attached source code also.
Please rate the document and share with your friend if you found it as useful.