Use data template based on property - c#

Is it possible to control which DataTemplate a node used based on a property rather than the class type which is typically seen in wpf.
In my case I have a list of teams and I want to control the background of each team being listed in the listbox as well as a few other design elements such as displaying different logos based on which team. In my mind it seems easiest to just make a data template based on the team name.
How do you guys suggest I handle it. I don't want to create a class object for every entire team. However it would be ideal if a team doesn't have a design template that a default one gets used.
Either way if someone could put together a super simple example Id appreciate it considering im not sure how to do it .

From what you described, it seems to me that those property can be hold on the Team class and you could display the content based on them !, but since you might need something much complicated you could use a DataTemplateSelector basically what you need to do is :
First : In resources area define the DataTemplates that you need plus a default one, in case none of the teams names matche a difined template,
lets say something like that :
<Window.Resources>
<DataTemplate x:Key="DefaultnDataTemplate" DataType="{x:Type YourNameSpace:Team}">
<Grid Background="LightGreen">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="DefaultnDataTemplate"/>
<TextBlock Text="{Binding Id}" Grid.Row="1" Grid.Column="0"/>
<TextBlock Text="{Binding Name}" HorizontalAlignment="Center" Grid.Row="1" Grid.Column="1"/>
<TextBlock Text="{Binding Matches}" Grid.Row="1" Grid.Column="2"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="TeamADataTemplate" DataType="{x:Type YourNameSpace:Team}">
<Grid Background="LightCoral">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="TeamADataTemplate"/>
<TextBlock Text="{Binding Id}" Grid.Row="1" Grid.Column="0"/>
<TextBlock Text="{Binding Name}" HorizontalAlignment="Center" Grid.Row="1" Grid.Column="1"/>
<TextBlock Text="{Binding Matches}" Grid.Row="1" Grid.Column="2"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="TeamBDataTemplate" DataType="{x:Type YourNameSpace:Team}">
<Grid Background="LightBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="TeamBDataTemplate"/>
<TextBlock Text="{Binding Id}" Grid.Row="1" Grid.Column="0"/>
<TextBlock Text="{Binding Name}" HorizontalAlignment="Center" Grid.Row="1" Grid.Column="1"/>
<TextBlock Text="{Binding Matches}" Grid.Row="1" Grid.Column="2"/>
</Grid>
</DataTemplate>
</Window.Resources>
Second add a DataTemplateSelector class, the class will basically check the team name and return the appropriate DataTemplate:
public class TeamDataTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultnDataTemplate { get; set; }
public DataTemplate TeamADataTemplate { get; set; }
public DataTemplate TeamBDataTemplate { get; set; }
public override DataTemplate SelectTemplate(object item,
DependencyObject container)
{
var teamName = (item as Team).Name;
switch (teamName)
{
case "TeamA":
return TeamADataTemplate;
case "TeamB":
return TeamBDataTemplate;
default:
return DefaultnDataTemplate;
}
}
}
Third, add an instance of that class to the StaticResources, and point it to the already defined DataTemplates :
<YourNameSpace:TeamDataTemplateSelector x:Key="TeamDataTemplateSelector" TeamADataTemplate="{StaticResource TeamADataTemplate}" TeamBDataTemplate="{StaticResource TeamBDataTemplate}" DefaultnDataTemplate="{StaticResource DefaultnDataTemplate}"/>
Finally call the TemplateSelector in your List:
<ListBox ItemsSource="{Binding Teams}" ItemTemplateSelector="{StaticResource TeamDataTemplateSelector}">
</ListBox>
here the model i am using in this sample :
public class Team
{
public string Name { get; set; }
public string Id { get; set; }
public string Matches { get; set; }
}
private ObservableCollection<Team> _teams=new ObservableCollection<Team>()
{
new Team()
{
Id="1",
Matches = "45",
Name = "TeamA"
},
new Team()
{
Id="1",
Matches = "45",
Name = "TeamB"
},
new Team()
{
Id="1",
Matches = "45",
Name = "TeamC"
}
};
public ObservableCollection<Team> Teams
{
get
{
return _teams;
}
set
{
if (_teams == value)
{
return;
}
_teams = value;
OnPropertyChanged();
}
}

Related

How to use WPF DataTemplates only on a part of the layout

In a MVVM environment I am using a list box where I am visualizing different data types in a different way but having some style elements in common. A minimal sample looks like this:
interface IPropertyItem
{
string Description { get; }
}
class PropertyBoolItem : IPropertyItem
{
public string Description { get; }
public bool Value { get; set; }
}
class PropertyStringItem : IPropertyItem
{
public string Description { get; }
public string DifferentValue { get; set; }
}
<ListBox>
<ListBox.Resources>
<!-- A bool item -->
<DataTemplate DataType="{x:Type types:PropertyBoolItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text{Binding Description}/>
<CheckBox Grid.Column="3" IsChecked="{Binding Value}"/>
</Grid>
</DataTemplate>
<!-- A string item -->
<DataTemplate DataType="{x:Type types:PropertyStringItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text{Binding Description}/>
<TextBox Grid.Column="3" Text="{Binding DifferentValue, Mode=TwoWay}"/>
</Grid>
</DataTemplate>
<!-- and so on... -->
</ListBox.Resources>
</ListBox>
Everythings is working so far. But I was wondering if there is a more elegant way to implement this as big parts of the markup are always the same and only some parts (as the checkbox or the textbox) are dependent on the data type.
Thanks in advance!
Not sure if this qualifies as "more elegant", but it is less XAML, and you wouldn't have to bother with the complex ListBoxItem Template.
<ListBox ...>
<ListBox.Resources>
<!-- A bool item -->
<DataTemplate DataType="{x:Type types:PropertyBoolItem}">
<CheckBox IsChecked="{Binding Value}"/>
</DataTemplate>
<!-- A string item -->
<DataTemplate DataType="{x:Type types:PropertyStringItem}">
<TextBox Text="{Binding DifferentValue}"/>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Description}"/>
<ContentPresenter Grid.Column="3" Content="{Binding}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Can`t bind entry and property in two way mode

Try to create simple app that will add items to the list. Have problems with binding entries with properties in ViewModel.
Here is my xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModels="clr-namespace:MyScoreDemo.ViewModels;assembly=MyScoreDemo"
x:Class="MyScoreDemo.Views.ClubListPage">
<StackLayout
Padding="15"
Spacing="10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="Name:" Grid.Row="0" Grid.Column="0"/>
<Entry x:Name="EntryName" Text="{Binding Club.Name, Mode=OneWayToSource}" Grid.Row="0" Grid.Column="1"/>
<Label Text="Country:" Grid.Row="1" Grid.Column="0"/>
<Entry x:Name="EntryCountry" Text="{Binding Club.Country, Mode=OneWayToSource}" Grid.Row="1" Grid.Column="1"/>
<Button Text="Add" Command="{Binding AddCommand}" CommandParameter="{x:Reference EntryName}"
Grid.Row="2" Grid.ColumnSpan="2" Grid.Column="0" />
</Grid>
<ListView ItemsSource="{Binding Clubs}"
Margin="5">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Path=Name}"/>
<Label Text="{Binding Path=Country}" Grid.Column="1"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout.BindingContext>
<viewModels:ClubListViewModel/>
</StackLayout.BindingContext>
</StackLayout>
And ViewModel code:
private Club _club;
public ICommand AddCommand { get; set; }
public ICommand RemoveCommand { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Club> Clubs { get; set; }
public ClubListViewModel()
{
AddCommand = new Command(AddClub);
RemoveCommand = new Command(RemoveClub);
Clubs = new ObservableCollection<Club>();
}
public Club Club
{
get => _club;
set
{
_club = value;
OnPropertyChanged("Club");
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
//Commands
private void AddClub()
{
}
Set breakpoints in property`s Club set section and try different modes, but it never stops.
All that I need to change is ta add Club = new Club(); in constructor of my ViewModel class.

WPF - adding item of different template in listview

When item on my ListView is clicked I want to make another one of different template to appear below it. I have defined templates in Window.Resources and I thought about changing ItemTemplate when item is clicked, adding new item and changing it to default template, but i am using list with my ListView as ItemsSource it showed only one template and only because (for now) both of them are the same in bindings. What should i do?
Code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<TransactionItem> item = new List<TransactionItem>();
item.Add(new TransactionItem() { category="Deska", index="2", name="Topielec"});
List<object> transactions = new List<object>();
transactions.Add(new Transaction() { name = "Maciek", surname = "Chludzinski", begin = "Dzisiaj 20:14", end = "Dzisiaj 21:14", price = "240 zł", remain = "42 minuty", items = item });
obMainListBinding.ItemTemplate = (DataTemplate)this.FindResource("LessClientTemplate");
MessageBox.Show(obMainListBinding.ItemTemplate.DataTemplateKey.ToString());
transactions.Insert(1, new Transaction() { name = "jhadf", surname = "Chludzhadfi", begin = "Dhad:14", end = "Dzisiajah", price = "240 zł", remain = "42 minuty"});
obMainListBinding.ItemTemplate = (DataTemplate)this.FindResource("BasicTransactionTemplate");
obMainListBinding.ItemsSource = transactions;
}
public class Transaction
{
public string name { get; set; }
public string surname { get; set; }
public string begin { get; set; }
public string end { get; set; }
public string remain { get; set; }
public string price { get; set; }
public List<TransactionItem> items { get; set; }
}
public class TransactionItem
{
public string category { get; set; }
public string index { get; set; }
public string name { get;set; }
}
public class LessTransaction
{
public string name { get; set; }
public string surname { get; set; }
public string begin { get; set; }
public string end { get; set; }
public string remain { get; set; }
public string price { get; set; }
}
}
XAML:
<Window
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" x:Class="SurfManager.MainWindow"
Title="MainWindow" Height="524.5" Width="1078">
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded"/>
</Window.Triggers>
<Window.Resources>
<DataTemplate x:Key="BasicTransactionTemplate">
<Grid MaxHeight="50">
<Grid.RowDefinitions>
<RowDefinition Height="41*"/>
<RowDefinition Height="42*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition Width="192*"/>
<ColumnDefinition Width="234*"/>
<ColumnDefinition Width="189*"/>
<ColumnDefinition Width="443*"/>
</Grid.ColumnDefinitions>
<Label Name="Name" Content="{Binding name}" Grid.RowSpan="1" Grid.Column="1" Grid.ColumnSpan="1" />
<Label Name="Surname" Content="{Binding surname}" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="1"/>
<Label Name="Begin" Content="{Binding begin}" Grid.Column="2"/>
<Label Name="End" Content="{Binding end}" Grid.Row="1" Grid.Column="2"/>
<Label Name="Remain" Content="{Binding remain}" Grid.Column="3"/>
<Label Name="Price" Content="{Binding price}" Grid.Row="1" Grid.Column="3"/>
<ListView Name="lvItems" ItemsSource="{Binding items}" Grid.Column="4" Grid.RowSpan="2">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding category}" />
<TextBlock Text=", Nr" />
<TextBlock Text="{Binding index}" />
<TextBlock Text="{Binding name}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
<DataTemplate x:Key="LessClientTemplate">
<Grid MaxHeight="50">
<Grid.RowDefinitions>
<RowDefinition Height="41*"/>
<RowDefinition Height="42*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition Width="192*"/>
<ColumnDefinition Width="234*"/>
<ColumnDefinition Width="189*"/>
<ColumnDefinition Width="443*"/>
</Grid.ColumnDefinitions>
<Label Name="Name" Content="{Binding name}" Grid.RowSpan="1" Grid.Column="1" Grid.ColumnSpan="1" />
<Label Name="Surname" Content="{Binding surname}" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="1"/>
<Label Name="Begin" Content="{Binding begin}" Grid.Column="2"/>
<Button Name="End" Content="{Binding end}" Grid.Row="1" Grid.Column="2"/>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<TabControl>
<TabItem Header="Obecne Wypożyczenia" Background="#FFF40AFF" Foreground="Black" BorderBrush="#FF8C8E94" OpacityMask="White">
<Grid Background="#FFE5E5E5">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<ListView Name="obMainListBinding" BorderThickness="0" ItemTemplate="{StaticResource BasicTransactionTemplate}">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border Background="{TemplateBinding Background}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
</ListView>
</Grid>
</TabItem>
<TabItem Header="Baza Klientow">
<Grid Background="#FFE5E5E5">
<ListView BorderThickness="0" >
<ListViewItem Height="66" Background="Red">
<Grid Background="Black" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0*"/>
<ColumnDefinition Width="0*"/>
<ColumnDefinition Width="0*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="0*"/>
<RowDefinition Height="0*"/>
<RowDefinition Height="0*"/>
</Grid.RowDefinitions>
</Grid>
</ListViewItem>
</ListView>
</Grid>
</TabItem>
<TabItem Header="TabItem" HorizontalAlignment="Left" Height="35.293" VerticalAlignment="Top" Width="57.32" Margin="-2,-2,0,-13.333">
<Button Content="Button" Height="100" Margin="430,174,430,173"/>
</TabItem>
</TabControl>
You could try to use the ItemTemplateSelector property:
How do I use a ItemTemplateSelector together with a HeaderTemplate in a WPF ListView?
and(or) triggers that change Template:
How to change control template from Style.Triggers
EDIT
To use TemplateSelector you could add some dummy property on your items(or wrap them) that will allow you to discern new item from old.
...
public Int32 Generation
{
get ...
}
public class GenerationTypeSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var transaction = (TransactionItem)item;
if (transaction .Generation == 0)
return Gen0Template;
else
return Gen1Template;
}
}

Resize controls in a list to fill the available space WPF

I'm trying to find a way to display a horizontal List of items in WPF, the trick is that the Window which contains the List will be displayed on various screen sizes and all the items in the list need to be resized to fill the available space without any use of scroll bars.
I've found that a ViewBox control can be used to achieve the desired affect, but the ViewBox works only if I set <RowDefinition Height="300"/>.This approach doesn't work because if you have a certain number of items in the List they start becoming cut off.
If I remove <RowDefinition Height="300"/> then the first item in the list fills the screen and the rest are cut off
Any suggestions on how I can make all the items in the list resize to fill the available space no matter what the screen resolution is?
XAML:
<Window x:Class="ViewBoxExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowState="Maximized">
<ItemsControl ItemsSource="{Binding Path=Employees}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="300"/>
</Grid.RowDefinitions>
<Viewbox Grid.Row="0" Grid.Column="0">
<TextBlock Text="{Binding Path=Name}" />
</Viewbox>
<Viewbox Grid.Row="0" Grid.Column="1">
<TextBlock Text="{Binding Path=Surname}" />
</Viewbox>
<Viewbox Grid.Row="0" Grid.Column="2">
<TextBlock Text="{Binding Path=Age}" />
</Viewbox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
C#:
using System.Collections.Generic;
using System.Windows;
namespace ViewBoxExample
{
public partial class MainWindow : Window
{
public List<Employee> _employees = new List<Employee>();
public List<Employee> Employees
{
get { return _employees; }
set { _employees = value; }
}
public MainWindow()
{
InitializeComponent();
Employees = new List<Employee>()
{
new Employee{ Name="Name1",Surname="Surname1",Age=20},
new Employee{ Name="Name2",Surname="Surname2",Age=30},
new Employee{ Name="Name3",Surname="Surname3",Age=40},
new Employee{ Name="Name4",Surname="Surname4",Age=50},
new Employee{ Name="Name5",Surname="Surname5",Age=60},
};
this.DataContext = this;
}
}
public class Employee
{
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
}
}
Just put your ItemsControl in ViewBox
<Viewbox>
<ItemsControl ItemsSource="{Binding Path=Employees}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Viewbox Grid.Row="0" Grid.Column="0">
<TextBlock Text="{Binding Path=Name}" />
</Viewbox>
<Viewbox Grid.Row="0" Grid.Column="1">
<TextBlock Text="{Binding Path=Surname}" />
</Viewbox>
<Viewbox Grid.Row="0" Grid.Column="2">
<TextBlock Text="{Binding Path=Age}" />
</Viewbox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Viewbox>
EDIT: if i am doing the same type of thing i would use the actual Height and Width approach as explained by Kent Boogaart in this Answer

How to pass data between the View and the ViewModel

I'm a newbie in the MVVM design patter I'm trying to create a simple app where a list of students is shown in the main window and I want the user to be able to add a new student to the list I have accomplished the binding of the observable collection where the students' data are but how can I create a new user by fetching the data from the textboxes and using them as a parameter in a command
Here is my View
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="NameTextBlock"
Text="Name"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBlock x:Name="SurnameTextBlock"
Grid.Row="1"
Text="Surname"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBlock x:Name="AgeTextBlock"
Grid.Row="2"
Text="Age"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBox x:Name="NameTextBox"
Grid.Column="1"
Style="{StaticResource TextBoxTextStyle}"/>
<TextBox x:Name="SurnameTextBox"
Grid.Row="1"
Grid.Column="1"
Style="{StaticResource TextBoxTextStyle}"/>
<TextBox x:Name="AgeTextBox"
Grid.Row="2"
Grid.Column="1"
Style="{StaticResource TextBoxTextStyle}"/>
<ListBox x:Name="StudentListBox"
Grid.ColumnSpan="2"
Grid.Row="4"
Style="{StaticResource ListBoxStyle}"
ItemsSource="{Binding StudentList}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBlock Text="{Binding Surname}"
Grid.Column="1"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBlock Text="{Binding Age}"
Grid.Column="2"
Style="{StaticResource TextBlockTextStyle}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="AddButton"
Grid.Row="7"
Grid.ColumnSpan="2"
HorizontalAlignment="Center"
Content="Add"
Margin="7,7,7,7"
Command="{Binding AddStudentCommand}"/>
</Grid>
And here is my ViewModel
public class MainViewModel : ViewModelBase
{
ObservableCollection<Student> studentList;
public MainViewModel()
{
//populate some sample data
studentList = new ObservableCollection<Student>()
{
new Student(){Name="John", Surname="Smith", Age="28"},
new Student(){Name="Barbara", Surname="Anderson", Age="23"}
};
}
public ObservableCollection<Student> StudentList
{
get { return studentList; }
set { RaisePropertyChanged("studentList"); }
}
Student selectedPerson;
public Student SelectedPerson
{
get { return selectedPerson; }
set
{
selectedPerson = value;
RaisePropertyChanged("SelectedPerson");
}
}
private RelayCommand _addStudentCommand;
public ICommand AddStudentCommand
{
get
{
return _addStudentCommand
?? (_addStudentCommand = new RelayCommand(() =>
{
Student student = new Student();
// here should be the logic of defining the name, surname,
// age and id of the newly created student
studentList.Add(student);
}));
}
}
}
I am using MVVMLight in the current project and there are a lot of thing that I do not understand so please explain how I should pass the data of the textboxes and what exactly should happen in the command that it is being used.
Tell me to add more of the code if necessary.
What I would do is create some properties that the textboxes are bound to in the ViewModel.
Like this for all three (in your viewmodel)
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
RaisePropertyChanged("Name");
}
}
Then, in the XAML, bind the textbox's text to this:
<TextBox x:Name="NameTextBox"
Text="{Binding Name}"
Grid.Column="1"
/>
Finally in the AddStudent Command you reference the properties in the viewmodel that are bound to the textboxes.
private RelayCommand _addStudentCommand;
public ICommand AddStudentCommand
{
get
{
return _addStudentCommand
?? (_addStudentCommand = new RelayCommand(() =>
{
Student student = new Student();
student.Name = this.Name;
student.Surname = this.Surname;
student.Age = this.Age;
// here should be the logic of defining the name, surname,
// age and id of the newly created student
_StudentList.Add(student);
}));
}
}
(cheekily posted from my comment)
As you've stated, you've not had much experience and don't understand much with MVVM, so although I could answer this question, I think the best thing I could do is provide you with a few links to watch :
youtube.com/watch?v=BClf7GZR0DQ
and
channel9.msdn.com/blogs/kreekman/
The second video is from the guy who wrote MVVM-light.
They basically cover the same material, but both bring a slightly different perspective!

Categories

Resources