'How properly use binding in wpf?
Let say I got app that is going to read data from database.
So in c# i got class like this:
public class Employee {
public string Name { get; set; }
public string Title { get; set; }
}
And my wpf window looks like:
<TextBlock Margin = "10" Width = "100" Text = "{Binding Name}" />
As I understand, to display in my window name of the employee I should use DataContext to bind object Employee with my wpf:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = new Employee(...);
}
Ok, but what if i have another textbox to display object from another class?
public class Movie {
public string MovieTitle { get; set; }
}
<TextBlock Margin = "10" Width = "100" Text = "{Binding MovieTitle}" />
Where should I use DataContext to bind this all, that two textbox are display on my screen, and both display properties from another object?
Solution 1:[1]
It's not a must, but in WPF it is recommended to follow MVVM design patterns.
This means you need a View (as you created), a Model and a ViewModel.
The View should have a DataContext point to a ViewModel, and the binding in the View's XAML should be pointing to the ViewModel's properties.
So in your case, you can create a "main" ViewModel as your main DataContext object, and this ViewModel can have a string property called "EmployeeName" (or Employee ViewModel object with property "Name") and then the property can be assigned, or fetch the information directly from the Model.
Do not forget to fire a property change notification from the setter of any view model property, e.g. the PropertyChanged event of the INotifyPropertyChanged interface.
public string EmployeeName
{
get { return _employeeModel.Name; }
set
{
_employeeModel.Name = value;
PropertyChanged?.Invoke(
this, new PropertyChangedEventArgs(nameof(EmployeeName)));
}
}
If you're following MVVM properly:
- Your ViewModel must not know the View, it can only know Models or other ViewModels.
- Your Model must not know the View or the ViewModel, it can only know other Models.
Solution 2:[2]
As others were trying to point out, add another thing to the main class. Or, as Yair mentioned to create a view model. Try to think of it this way.
public class MainWindowViewModel
{
public MainWindowViewModel()
{
OneEmployee = new Employee();
OneMovie = new Movie();
}
public Employee OneEmployee {get; set;}
public Movie OneMovie {get; set;}
// any other things you want to expose, button relay commands labels, etc...
public string SomeOtherThing {get; set;}
}
Now, in your MainWindow (or whatever other secondary window you develop), in its constructor, just set
DataContext = new MainWindowViewModel();
Now, back to your XAML Your xaml's data context is to the overall view model that has BOTH objects, a label, and whatever else you want. When binding and its all in the same level in the xaml, you can do binding to OneEmployee.Name, or OneMovie.Title, or whatever other parts going on.
However, let say you are sectioning off the display and have one area designated for the employee information and another based on a movie. You can set a data context to that sub-component to the object in question, so the inner controls are now defaulted to that. Removes the need of "object.property" notation within. Ex:
<UserControl DataContext="{Binding OneEmployee}">
<Grid>
<define your grid rows/columns for example>
<Label Content="Name" Grid.Row="0" Grid.Column="0" />
<TextBox Width="100" Grid.Row="0" Grid.Column="1"
Text="{Binding Name}" />
</Grid>
</UserControl>
Notice above the entire "UserControl" has its default data context to just the OneEmployee object. So everything within can refer to properties exposed directly on that object. In this example, the entire context of the user control is to show information about the one employee and not the movie. Same can be done for a single movie.
I actually like doing it this way and create individual user controls with inner grid type content to span its own rows/columns. Then, when I put them into a main view area, I dont have to worry about messing with other nested controls, grids. The single user-control is all self-contained with all its alignments, borders, etc. If I need to adjust employee info layout, I just change that one class, not the outer view that the employee is displayed within.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Clemens |
| Solution 2 | DRapp |
