Silverlight the first combobox filter the second combobox
I have two comboboxes created as common controls. When the page is loaded, the programcbo lists the programs names; and the teamcbo list the team names. I want to ONLY display the related team names when any program name has been selected. In开发者_如何学编程 a word, I need to filter the second combobox by selecting the name from the first combobox.
Thanks in advance.
There are a variety of ways you could handle this.
If you have, for example, "Program" objects that contain collections of "Teams", you could do it like this, almost all in XAML:
<StackPanel>
<ComboBox x:Name="programCbo" ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ProgramName}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox x:Name="teamCbo" ItemsSource="{Binding ElementName=programCbo, Path=SelectedItem.Teams}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TeamName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
You can see here that I've bound the first combobox to the datacontext, which is a list of Programs (we'll set that in the next bit). The second combobox is set to the selecteditem property of the first combobox, and then the Teams property on that. This way, when the selection changes on the first combobox, databinding kicks in and causes the itemssource on the second box to update.
In the code behind, I just build up the datasource. Obviously you'd have to get your data your own way:
public MainPage()
{
InitializeComponent();
DataContext = new List<Program>
{
new Program
{
ProgramName = "Program 1",
Teams = new List<Team>
{
new Team
{
TeamName = "Program 1 Team 1"
},
new Team
{
TeamName = "Program 1 Team 2"
}
}
},
new Program
{
ProgramName = "Program 2",
Teams = new List<Team>
{
new Team
{
TeamName = "Program 2 Team 1"
},
new Team
{
TeamName = "Program 2 Team 2"
}
}
}
};
}
If you don't have your data in a way that's accessible like this, you'll have to handle the Selection changed event on your combobox:
(XAML)
<StackPanel>
<ComboBox x:Name="programCbo" SelectionChanged="programCbo_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ProgramName}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox x:Name="teamCbo">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TeamName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
Notice this time, we've set a handler for the SelectionChanged event.
(CodeBehind)
public MainPage()
{
InitializeComponent();
programCbo.ItemsSource = new List<Program>
{
new Program
{
ProgramName = "Program 1",
},
new Program
{
ProgramName = "Program 2",
}
};
}
private void programCbo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// get the sender
ComboBox cb = sender as ComboBox;
// get the selected program
Program selectedProgram = (cb.SelectedItem as Program);
// do some stuff to get the appropriate teams and set the other combobox's itemssource to it
teamCbo.ItemsSource = new List<Team>
{
new Team
{
TeamName = "My favorite team!"
}
};
}
And there you have it. Long winded, but hopefully thorough with examples :)
You can use a paged collection to filter or you can modify your observable collection which is bound to the second combobox when the value that's bound to the first combobox raises on prop change.
xaml:
...
xmlns:local="clr-namespace:SelectedProgram">
<UserControl.Resources>
<local:MainPageViewModel x:Key="vm" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource vm}}">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="350" />
</Grid.RowDefinitions>
<sdk:Label Content="Select Team for the Program" Grid.Row="0" Margin="20,0,0,0"/>
<StackPanel Orientation="Horizontal" Grid.Row="1" VerticalAlignment="Top" Margin="20,0,0,0">
<ComboBox x:Name="programcbo" Width="100" Height="25"
ItemsSource="{Binding Path=Programs, Mode=OneWay}"
SelectedValue="{Binding Path=SelectedTeam, Mode=TwoWay}"
DisplayMemberPath="Key"
SelectedValuePath="Value" />
<ComboBox x:Name="teamcbo" Width="100" Height="25" Margin="20"
ItemsSource="{Binding Path=SelectedTeam, Mode=OneWay}"/>
</StackPanel>
</Grid>
In class like MainPageViewModel:
...
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Windows.Data;
namespace SelectedProgram
{
public class MainPageViewModel : ModelBase
{
public MainPageViewModel()
{
this.Programs = GetPrograms();
}
private string[] _selectedTeam;
public string[] SelectedTeam
{
get { return _selectedTeam; }
set
{
_selectedTeam = value;
FirePropertyChanged("SelectedTeam");
}
}
private ObservableCollection<KeyValuePair<string, string[]>> _programs;
public ObservableCollection<KeyValuePair<string, string[]>> Programs
{
get { return _programs; }
set
{
_programs = value;
FirePropertyChanged("Programs");
}
}
private ObservableCollection<KeyValuePair<string, string[]>> GetPrograms()
{
ObservableCollection<KeyValuePair<string, string[]>> pr = new ObservableCollection<KeyValuePair<string, string[]>>();
pr.Add(new KeyValuePair<string, string[]>("Janitors", new string[]{ "Schwarzkopf", "Ivanov", "Smith"}));
pr.Add(new KeyValuePair<string, string[]>("Violonists", new string[] { "Einstein", "Odinzovobulyznicof", "Onestone" }));
pr.Add(new KeyValuePair<string, string[]>("Programers", new string[] { "Petrov", "Skeet", "Stroustrup" })); return pr;
}
}
}
精彩评论