Reputation: 934
I have a problem with correctly implementing a data binding with MVVM and a ComboBox
.
I have a simple Model:
public class RuleSet
{
public List<RuleMainSystem> RuleMainSystems { get; set; }
public RuleSet()
{
RuleMainSystems = new List<RuleMainSystem>();
}
}
And therein it looks like this:
public class RuleMainSystem
{
public string Name { get; set; }
public List<RuleSubSystem> RuleSubSystems { get; set; }
public RuleMainSystem(string name)
{
Name = name;
RuleSubSystems = new List<RuleSubSystem>();
}
}
I want now a simple binding from a page where a ComboBox
is part of and the ItemSource
of this ComboBox
to be set to this RuleSet
.
I tried to bind directly to the ViewModel, but this one is deleted from the RAM as soon as I navigate to another site and I want to avoid as much static
's as possible, so I created an instance of this ViewModel on the first site and give it to the second page as a parameter. That works well so far, but now I would have to bind the ComboBox
to this._editRulesViewModel.RuleSet.RuleMainSystems
and that's where I don't get the right code.
Maybe I approach this from the wrong side? A suggestion how I could access the data from one site to another without giving the whole instances from A to B to C and so on?
This doesn't work:
View:
public sealed partial class EditRules
{
private EditRulesViewModel _editRulesViewModel;
public EditRules()
{
DataContext = this;
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
_editRulesViewModel = (EditRulesViewModel)e.Parameter;
}
}
And in the XAML:
<ComboBox x:Name="MainSystemComboBox" DisplayMemberPath="Name" ItemsSource="_editRulesViewModel.RuleSet.RuleMainSystems" />
I mean, yes, the data arrives at the second page, but the Binding
is wrong.
Oh and I also tried to set the DataContext in the XAML Page definition:
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Upvotes: 0
Views: 40
Reputation: 39072
First, {Binding}
does not work with private
fields. Instead, you must expose them as public
properties. The newer {x:Bind}
extension does work with public
fields, but still not with private
.
Next - you need to use {Binding}
syntax in all places that do data-binding - so for ItemsSource
as well, it is not enough to write the variable name directly.
Finally, to make it all working, you will also need to implement INotifyPropertyChanged
on the page, because during OnNavigatedTo
the data-binding has already run, so it will not bind the newly assigned value otherwise.
public sealed partial class EditRules : INotifyPropertyChanged
{
public EditRulesViewModel EditRulesViewModel {get; private set;}
public EditRules()
{
DataContext = this;
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
EditRulesViewModel = (EditRulesViewModel)e.Parameter;
OnPropertyChanged(nameof(this.EditRulesViewModel));
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Now in XAML do:
<ComboBox x:Name="MainSystemComboBox" DisplayMemberPath="Name"
ItemsSource="{Binding EditRulesViewModel.RuleSet.RuleMainSystems}" />
Upvotes: 1
Reputation: 496
you could try to implement the INotifyPropertyChanged-Event.
Or add Elements to a list like so:
public sealed partial class EditRules
{
private List<object> _editRulesViewModel = new List<object>();
public EditRules()
{
DataContext = this;
InitializeComponent();
}
//Add nullchecking, etc.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
_editRulesViewModel.Clear();
foreach (item in ((EditRulesViewModel)e.Parameter)RuleSet.RuleMainSystems)
{
_editRulesViewModel.Add(item);
}
}
}
<ComboBox x:Name="MainSystemComboBox" DisplayMemberPath="Name" ItemsSource="_editRulesViewModel" />
Upvotes: 1