I can bind a combobox in the codebehind like this:
private void comboBox1_Loaded(object sender, RoutedEventArgs e) { var combo = sender as ComboBox; App.SchedulerVM = new ScheduleViewModel(); combo.DataContext = App.SchedulerVM; combo.ItemsSource = App.SchedulerVM.Frequency; } This works - my combobox has the items from the Frequency List in the SchedulerVM object.
However, I don't want to do any of this in the codebehind. But the ways I've done this in WP7 before aren't working here. If I comment out the last line in the Loaded method above and try to set the ItemsSource in XAML, it doesn't work - nothing shows up:
<ComboBox Name="comboBox1" Loaded ="comboBox1_Loaded" ItemsSource="{Binding Frequency}" /> This doesn't work either:
<ComboBox Name="comboBox1" Loaded ="comboBox1_Loaded" ItemsSource="{Binding App.SchedulerVM.Frequency}" /> Nor this:
<ComboBox Name="comboBox1" Loaded ="comboBox1_Loaded" ItemsSource="{Binding SchedulerVM.Frequency}" /> Ideally, the DataContext wouldn't have to be explicitly set in the codebehind for this control either, it would be inherited from the LayoutRoot, where I've set it in the codebehind. But that's step 2 of my troubleshooting here.
What am I doing wrong? '
Thanks!
Edit The ScheduleViewModel looks like this:
namespace SchedulerUI.ViewModels { public class ScheduleViewModel : INotifyPropertyChanged { //private properties private Schedule _thisSchedule; //public properties public Schedule ThisSchedule { get { return _thisSchedule; } set { if (value != _thisSchedule) { NotifyPropertyChanged("ThisSchedule"); } _thisSchedule = value; } } public List<string> Frequency = new List<string>(); public string Test; //constructors public ScheduleViewModel() { Frequency.AddRange(new string[] { "Daily", "Weekly", "Monthly" }); Test = "This is only a test."; } //INotifyPropertyChanged Implementation public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (null != handler) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } } Here's the entire XAML:
<UserControl x:Class="SchedulerUI.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"> <Grid x:Name="LayoutRoot" Background="White" Loaded="LayoutRoot_Loaded"> <ComboBox Height="23" HorizontalAlignment="Left" Margin="34,41,0,0" Name="comboBox1" Loaded ="comboBox1_Loaded" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Frequency}" /> <TextBox BorderBrush="Black" HorizontalAlignment="Left" Margin="34,41,0,0" Width="100" Height="100" DataContext="LayoutRoot.DataContext" Text="{Binding Test}" /> </Grid> </UserControl> Here's the entire codebehind:
namespace SchedulerUI { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); App.SchedulerVM = new ScheduleViewModel(); comboBox1.DataContext = App.SchedulerVM; List<string> testlist = App.SchedulerVM.Frequency; string teststring = App.SchedulerVM.Test; } private void LayoutRoot_Loaded(object sender, RoutedEventArgs e) { //App.SchedulerVM = new ScheduleViewModel(); //var root = sender as Grid; //if (root != null) //{ // root.DataContext = App.SchedulerVM; //} } private void comboBox1_Loaded(object sender, RoutedEventArgs e) { //var combo = sender as ComboBox; //App.SchedulerVM = new ScheduleViewModel(); //combo.DataContext = App.SchedulerVM; //combo.ItemsSource = App.SchedulerVM.Frequency; } } } Answer: 1
You binding is not working, because:
- when you set
ItemsSourceinXAMLits get executed first and it tries to bind the wrong/emptyDataContext - then the
Loadedevent is raised which will set the correctDataContextbut your already existing binding won't be refreshed automatically.
If you have to set the DataContext in the codebehind do it in your views constructor:
public YourView() { InitializeComponent(); combo.DataContext = App.SchedulerVM; } Then the following binding should work:
<ComboBox Name="comboBox1" ItemsSource="{Binding Frequency}" /> The databinding in WPF/Silverlight needs public properties. Currently Frequency is a public field on your viewmodel change it to a property and everthing should work:
private List<string> frequency = new List<string>(); public List<string> Frequency { get { return frequency; } set { frequency = value; } And that is why it worked your initial loaded event because you didn't used databind there but you just set the combo.ItemsSource.
No comments:
Post a Comment
Send us your comment related to the topic mentioned on the blog