Reputation: 737
I'm building a Windows Universal app and trying to expose data from my ViewModel to my View so that I can bind it to XAML elements. I have completely commented out all of my code at this point and am just writing lines of test code to try and get it to work, that is what is in the examples below. Binding directly from the View (if I create an object there as a test) does work.
Please help me to understand where I am going wrong, I think I've read every binding tutorial on the internet and still just don't get it.
View (MainPage.xaml.cs):
public MainPage()
{
InitializeComponent();
DataContext = new MainViewModel();
}
ViewModel (MainViewModel.cs):
public class MainViewModel
{
public Term newTerm = new Term
{
TermName = "Table",
TermDescription = "You eat dinner on it"
};
}
XAML (MainPage.xaml):
<StackPanel DataContext="{Binding newTerm}" x:Name="mvvmStack" Orientation="Vertical">
<TextBlock x:Name="mvvmTermName" Text="{Binding TermName, FallbackValue='Fallingback'}" />
<TextBlock x:Name="mvvmDescription" Text="{Binding TermDescription, FallbackValue='Fallingback', TargetNullValue='Unknown'}" />
</StackPanel>
The error I get is:
Error: BindingExpression path error: 'newTerm' property not found on ''. BindingExpression: Path='newTerm' DataItem=''; target element is 'Windows.UI.Xaml.Controls.StackPanel' (Name='mvvmStack'); target property is 'DataContext' (type 'Object')
I have read about this type of error and although I have some idea of what it is trying to say I cannot work out how to fix it. I'm very much a complete beginner with coding, especially C# so please take that into account when answering :-)
Upvotes: 0
Views: 513
Reputation: 938
Try something like that:
<Page.Resources>
<viewModels:MainViewModel x:Key="MainViewModel" />
</Page.Resources>
And then:
<StackPanel x:Name="mvvmStack" Orientation="Vertical">
<TextBlock x:Name="mvvmTermName" Text="{Binding newTerm.TermName, Source={StaticResource MainViewModel} FallbackValue='Fallingback'}" />
<TextBlock x:Name="mvvmDescription" Text="{Binding newTerm.TermDescription, Source={StaticResource MainViewModel} FallbackValue='Fallingback', TargetNullValue='Unknown'}" /></StackPanel>
Of cource newTerm
should be an property with INotifyChanged
Upvotes: 0
Reputation: 491
Just try to change it from field to a property and it will be working correctly. You can't bind to fields. EDIT:
private Term _term;
public Term NewTerm{
get{return _term;}
set
{
_term= value;
OnPropertyChanged("Term");
}
}
if you need to add notify the view of changes in the viewmodel you need to implement INotifyPropertyChanged. check this answer it will provide an example for property changed. https://stackoverflow.com/a/27685925/1448382
If you want to bind the view to sub properties, you have two options depending on the situation:
1- Relative Binding: this scenario is used when you will not modify the properties inside the Term object from the ViewModel i.e. they will be just initialized in the viewmodel and can be modified in the view, just like the way you are doing it. Plesae note, that anything you need to bind to should be a property and not a field.
2- Binding to Viewmodel directly: this scenario is used when you will modify the properties inside the Term object from the Viewmodel after the view load. This way you will need to add properties to the viewmodel for the properties TermName and TermDescription.
public string TermName{
get{return NewTerm.Name;}
set{NewTerm.Name = value;
OnPropertyChanged("TermName");
}//The same is applied for TermDescription
But be aware that you will need to remove the binding on the Stackpanel object since you have defined the properties directly in the Viewmodel.
Upvotes: 3