Show data from textboxes into listview in wpf - c#

I have a C# project have :
The XAML Code:
<Window x:Class="Revision.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Patient Information" Height="456.36" Width="935.208">
<Window.Resources>
<Style x:Key="SliderStyle">
<Setter Property="FrameworkElement.Width" Value="100"/>
<Setter Property="RangeBase.Minimum" Value="0"/>
<Setter Property="RangeBase.Maximum" Value="100"/>
<Setter Property="Slider.IsSnapToTickEnabled" Value="true"/>
<Setter Property="FrameworkElement.VerticalAlignment" Value="Center"/>
<Setter Property="RangeBase.Value" Value="0"/>
<Setter Property="Slider.AutoToolTipPlacement" Value="TopLeft"/>
</Style>
</Window.Resources>
<Grid>
<Label Content="First Name" Height="28" HorizontalAlignment="Left" Margin="19,23,0,0" Name="label1" VerticalAlignment="Top" />
<Label Content="Last Name" Height="28" HorizontalAlignment="Left" Margin="19,82,0,0" Name="label2" VerticalAlignment="Top" />
<Label Content="Address" Height="28" HorizontalAlignment="Left" Margin="20,144,0,0" Name="label3" VerticalAlignment="Top" />
<Label Content="Security Type" Height="28" HorizontalAlignment="Left" Margin="19,203,0,0" Name="label4" VerticalAlignment="Top" />
<TextBox Height="36" HorizontalAlignment="Left" Margin="105,23,0,0" Name="textBox1" VerticalAlignment="Top" Width="197" />
<TextBox Height="36" HorizontalAlignment="Left" Margin="105,82,0,0" Name="textBox2" VerticalAlignment="Top" Width="197" />
<TextBox Height="36" HorizontalAlignment="Left" Margin="105,136,0,0" Name="textBox3" VerticalAlignment="Top" Width="197" />
<ComboBox Height="36" Margin="105,195,625,0" Name="comboBox1" VerticalAlignment="Top">
<ComboBoxItem Content="Private Assurance" Name="PrA"/>
<ComboBoxItem Content="Public Assurance" Name="PA"/>
<ComboBoxItem Content="No Assurance" Name="NA"/>
</ComboBox>
<Button Content="Submit" Height="33" HorizontalAlignment="Left" Margin="147,365,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click"/>
<Button Content="Display" Height="33" HorizontalAlignment="Left" Margin="227,365,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click" />
<Label Content="Gender" HorizontalAlignment="Left" Margin="20,255,0,0" VerticalAlignment="Top"/>
<RadioButton x:Name="maleRadio" Content="Male" HorizontalAlignment="Left" Margin="105,266,0,0" VerticalAlignment="Top"/>
<RadioButton x:Name="femaleRadio" Content="Female" HorizontalAlignment="Left" Margin="192,266,0,0" VerticalAlignment="Top"/>
<Slider x:Name="redSlider" Style="{StaticResource SliderStyle}" Value="{Binding Text, ElementName=textBox5}" Margin="74,313,636,56" SmallChange="1" Height="56" Width="Auto" />
<TextBox x:Name="textBox5" Text="{Binding Value, ElementName=redSlider}" Margin="296,313,588,86" SelectionOpacity="1" FontSize="13" />
<Label Content="Age" HorizontalAlignment="Left" Margin="38,313,0,0" VerticalAlignment="Top"/>
<ListView x:Name="ListView1" HorizontalAlignment="Left" Height="375" Margin="344,23,0,0" VerticalAlignment="Top" Width="567">
<ListView.View>
<GridView>
<GridViewColumn Header="First Name" Width="100"
DisplayMemberBinding="" />
<GridViewColumn Header="Last Name" Width="80"
DisplayMemberBinding="" />
<GridViewColumn Header="Address" Width="100"
DisplayMemberBinding="" />
<GridViewColumn Header="Security Type" Width="80"
DisplayMemberBinding="" />
<GridViewColumn Header="Gender" Width="100"
DisplayMemberBinding="" />
<GridViewColumn Header="Age" Width="100"
DisplayMemberBinding="" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
and I have a class patient:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Revision
{
class Patient
{
public string firstname { get; set; }
public string lastname { get; set; }
public string Address { get; set; }
public string securityType {get; set;}
public string gender { get; set; }
public string age { get; set; }
public Patient(string fn, string ln, string ad, string st,string ge,string ag)
{
firstname = fn;
lastname = ln;
Address = ad;
securityType = st;
gender = ge;
age = ag;
}
public override string ToString()
{
return string.Format("{0,-10} {1,-10} {2,-10} {3,-10} {4,-10} {5,-10}",
firstname, lastname, Address, securityType, gender,age);
}
}
}
and the main program
public partial class MainWindow : Window
{
// Patient [] patients = new Patient{}
Patient [] patients = new Patient[100];
private List<Patient> books = new List<Patient>();
int i=0;
string g;
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
string x = "";
if (PrA.IsSelected)
{
x = PrA.Content.ToString();
}
else if (PA.IsSelected)
{
x = PA.Content.ToString();
}
else if (NA.IsSelected)
{
x = NA.Content.ToString();
}
if (maleRadio.IsChecked == true)
g = "Male";
if(femaleRadio.IsChecked==true)
g="Female";
patients[i] = new Patient(
textBox1.Text, textBox2.Text, textBox3.Text, g, textBox5.Text, x);
i = i + 1;
// Patient[] patients = {
// new Patient (
// textBox1.Text, textBox2.Text, textBox3.Text, x)};
textBox1.Clear();
textBox2.Clear();
textBox3.Clear();
textBox5.Clear();
}
}
So the question I want to display the data entered in the textboxes,radio button and combo box... in the List view

The normal way of getting your data into the listview would be through databinding. Databinding is the way that WPF uses to transport data between your view and your code.
All wpf controls that can show multiple items, like listview, listbox, combobox etc, has a ItemSource property. By setting this property to an enumerable, the view will display each item in the collection.
By default, it will just render each item as a textblock showing the result of calling ToString() on each object. There are several ways of customizing this. In your case, you have defined columns with a GridView and GridViewColumns. Each GridViewColumn has a DisplayMemberBinding which can be binded to the property you want to display in that column.
So...
I'm not sure how easy it will be for you to use this. As mentioned by others, you really should learn a little bit about binding in wpf, and the Model-View-ViewModel (MVVM) pattern. MVVM really helps keeping the code clean.
Anyways...
Your view could be changed to something like this:
<ListView x:Name="ListView1" HorizontalAlignment="Left" Height="375" Margin="344,23,0,0" VerticalAlignment="Top" Width="567" ItemsSource="{Binding patients}">
<ListView.View>
<GridView>
<GridViewColumn Header="First Name" Width="100" DisplayMemberBinding="{Binding path=firstname}" />
<GridViewColumn Header="Last Name" Width="80" DisplayMemberBinding="{Binding path=lastname}" />
<GridViewColumn Header="Address" Width="100" DisplayMemberBinding="{Binding path=Address}" />
<GridViewColumn Header="Security Type" Width="80" DisplayMemberBinding="{Binding path=securityType}" />
<GridViewColumn Header="Gender" Width="100" DisplayMemberBinding="{Binding path=gender}" />
<GridViewColumn Header="Age" Width="100" DisplayMemberBinding="{Binding path=age}" />
</GridView>
</ListView.View>
</ListView>
I would change your fixed size array of patients to a ObservableCollection<Patient>. A collection that can grow in size is almost always better than a fixed size one. The ObservableCollection<> has some extra tricks as well. It will notify the view whenever items are added or removed.
Take a look at wpftutorial.net. You will find a nice introduction to binding , MVVM and a lot more.

Related

XAML Binding Observable Collection to DataGrid

I'm having trouble databinding based on other properties. My combobox is working fine, but the datagrids aren't. I'm was trying to bind the window to the codebehind using
DataContext="{Binding RelativeSource={RelativeSource Self}}" so I could have design time Intellisense, but I sort of got it using x:Name:"_Window"
The model for HRRM has lots of entities, and I know that that the properties I'm trying to bind too are spelt correctly etc. But I can't figure out why the DataGrid won't show the employees. I've also ensured that the data is being placed in the observable collection, and I've tried binding the items source just to ListEmployees and SmsEmployees and nothing I've tried has worked. This is the last bit of code I have tried.
<Window x:Class="GUI.Employees.Misc.SendSms"
x:Name="_Window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Send SMS" Height="525" Width="1000" DataContext="{Binding ElementName=_Window}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="270*" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="270*" />
</Grid.ColumnDefinitions>
<ComboBox Grid.Column="0" x:Name="cmbCompany" DisplayMemberPath="Name" ItemsSource="{Binding Path=Companies, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Margin="10,10,10,0" VerticalAlignment="Top" SelectionChanged="cmbCompany_SelectionChanged"/>
<DataGrid Grid.Column="0" x:Name="dgEmployees" Margin="10,37,10,10" IsReadOnly="True" AutoGenerateColumns="False" ItemsSource="{Binding Path=ListEmployees, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window} }">
<DataGrid.Columns>
<DataGridTextColumn Header="Company" Binding="{Binding HRCo }"/>
<DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" />
<DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
<DataGridTextColumn Header="Craft" Binding="{Binding StdCraft}"/>
</DataGrid.Columns>
</DataGrid>
<DataGrid x:Name="dgSendSms" Margin="10,37,10,10" IsReadOnly="True" Grid.Column="2" ItemsSource="{Binding SmsEmployees, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window} }">
<DataGrid.Columns>
<DataGridTextColumn Header="Company" Binding="{Binding HRCo}"/>
<DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" />
<DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
<DataGridTextColumn Header="Craft" Binding="{Binding StdCraft}"/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="cmdMoveAllHired" Content=">>" Margin="10,85,10,0" VerticalAlignment="Top" Grid.Column="1"
Click="cmdMoveAllHired_Click" />
<Button x:Name="cmdReturnSingleItem" Content=">" Margin="10,122,10,0" VerticalAlignment="Top"
Grid.Column="1" Click="cmdReturnSingleItem_Click" />
<Button x:Name="cmdMoveAllReturned" Content="<<" Margin="10,196,10,0" VerticalAlignment="Top"
Grid.Column="1" Click="cmdMoveAllReturned_Click" />
<Button x:Name="cmdHireSingleItem" Content="<" Margin="10,159,10,0" VerticalAlignment="Top" Grid.Column="1"
Click="cmdHireSingleItem_Click" />
<Button x:Name="cmdGenerate" Content="Generate" Grid.Column="1" Margin="10,0,10,10"
VerticalAlignment="Bottom" Click="cmdGenerate_Click" Visibility="Collapsed" />
<Button x:Name="cmdBack" Content="Back" Grid.Column="1" HorizontalAlignment="Left" Margin="10,249,0,0"
VerticalAlignment="Top" Width="130" Click="cmdBack_Click" />
<Button x:Name="cmdSendSMS" Content="Send SMS" Grid.Column="1" HorizontalAlignment="Left" Margin="10,316,0,0" VerticalAlignment="Top" Width="130" Click="cmdSendSMS_Click"/>
</Grid>
namespace GUI.Employees.Misc
{
public partial class SendSms
{
public ObservableCollection<HQCO> Companies { get; set; }
public ObservableCollection<HRRM> ListEmployees { get; set; }
private ObservableCollection<HRRM> _smsEmployees;
public ObservableCollection<HRRM> SmsEmployees {
get { return _smsEmployees; }
set { _smsEmployees = value;
}
}
public SendSms()
{
InitializeComponent();
Companies = new ObservableCollection<HQCO>(HQCO.GetActivePRCompanies());
Companies.Insert(0, new HQCO { HQCo = 0, Name = "All" });
// cmbCompany.SelectedItem = _companies.Single(x=>x.HQCo == 0);
SmsEmployees = new ObservableCollection<HRRM>();
ChangeCompany();
}
private void ChangeCompany()
{
if (((HQCO)cmbCompany.SelectedItem)?.HQCo == 0)
foreach (var co in Companies)
co.IsChecked = true;
else
foreach (var co in Companies)
if (((HQCO)cmbCompany.SelectedItem) == co)
co.IsChecked = true;
else
co.IsChecked = false;
ListEmployees = new ObservableCollection<HRRM>(Facade.GetEmployeePhoneNumbers(Companies.ToList(), false).OrderBy(x => x.SortName));
}
}
I think your problem is how you assign the DataContext of your Window. In your XAML, add a reference to the namespace so the Window can find your SendSms viewmodel, and then either assign the DataContext property in XAML (see below), or in the code-behind of your Window. If you set the DataContext this way, you shouldnt need to use RelativeSource when binding to the SendSms viewmodel, but if you want see changes, you also need to make sure the classes your observable collections are populated with implements INotifyPropertyChanged.
<Window x:Name="_Window"
xmlns:local="clr-namespace:GUI.Employees.Misc" >
<!-- set the DataContext of this Window to an instance of SendSms -->
<Window.DataContext>
<local:SendSms />
</Window.DataContext>
<DataGrid ItemsSource="{Binding ListEmployees}">
...
</DataGrid>
I don't believe your ListEmployees ItemsSource will update the DataGrid because it is not a DependencyProperty or you have not implemented INotifyPropertyChanged. It is not updating because you are assigning the property a new instance.
Instead try adding this to your constructor:
ListEmployees = new ObservableCollection<HRRM>();
And this to your ChangeCompany method:
foreach (var employee in Facade.GetEmployeePhoneNumbers(Companies.ToList(), false).OrderBy(x => x.SortName))
{
ListEmployees.Add(employee);
}
The above will actually make use of the ObservableCollection and it should then update the UI.

WPF ListView group and sort

I'm trying to group items on my list and sort them from oldest to newest. Grouping works perfect, it just doesn't want to inverse this list.
WPF Code:
<ListView x:Name="lst_orders" Margin="5" GridViewColumnHeader.Click="results_Click">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Setter Property="IsSelected" Value="true" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button x:Name="goto_parts" Content="Show parts" Width="AUTO" Padding="2" Margin="2" Background="#FF179917" Click="goto_parts_Click"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Order ID" Width="100" DisplayMemberBinding="{Binding fullOrderId}" />
<GridViewColumn Header="Job Status" Width="100" DisplayMemberBinding="{Binding status}" />
<GridViewColumn Header="Order Type" Width="150" DisplayMemberBinding="{Binding orderType}" />
<GridViewColumn Header="Customer Notes" Width="250" DisplayMemberBinding="{Binding notes}" />
<GridViewColumn Header="Admin Notes" Width="250" DisplayMemberBinding="{Binding adminNotes}" />
<GridViewColumn Header="Production Notes" Width="100" DisplayMemberBinding="{Binding production_notes}" />
</GridView>
</ListView.View>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Background="Gray">
<TextBlock Text="Days: " FontSize="18" FontWeight="Bold"/>
<TextBlock Text="{Binding Name}" FontSize="18" FontWeight="Bold"/>
<TextBlock Text=" Systems: " FontSize="18" FontWeight="Bold"/>
<TextBlock Text="{Binding ItemCount}" FontSize="18" FontWeight="Bold"/>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
C# Code:
ICollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(lst_orders.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("daysOld");
view.GroupDescriptions.Add(groupDescription);
view.SortDescriptions.Add(new SortDescription("daysOld", ListSortDirection.Descending));
lst_orders.ItemsSource = view;
daysOld is a property that calculates difference between today's date and order date, works perfect, but I want to see it from the highest number to the lowest. Picture shows what I get, and I want to reverse it.
Your code is correct.I've made a test. It is possible to see in view:
C#:
List<SomeClass> list = new List<SomeClass>();
Random rnd = new Random();
for (int i = 0; i < 10; i++)
{
list.Add(new SomeClass() { DaysOld = DateTime.Now.Add(new TimeSpan(0, rnd.Next(25), 0))});
}
ICollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(list);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("daysOld");
view.GroupDescriptions.Add(groupDescription);
view.SortDescriptions.Add(new SortDescription("DaysOld", ListSortDirection.Descending));
listBox.ItemsSource = view;
listBox.DisplayMemberPath = "DaysOld";
XAML:
<ListBox Name="listBox"/>
Model:
public class SomeClass
{
public DateTime DaysOld { get; set; }
}
Image:

how to access specific control in datatemplate generated listbox

So i have dataTemplate generated listbox like this:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Fill="{Binding color}" Height="10" Width="10" Grid.Column="1"/>
<TextBlock Text=" " Grid.Column="2"/>
<TextBlock Text="{Binding ID}" FontSize="10" FontWeight="Bold" Grid.Column="3"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate
and I bind it to ObservableCollection. I need to access specific item in this listbox and change colour of its rectangle element.
I would use a StyleSelector. make a styleselector like this:
ListViewItemStyleSelector.cs
public class ListViewItemStyleSelector : StyleSelector
{
public override Style SelectStyle(object item,
DependencyObject container)
{
Style st = new Style();
st.TargetType = typeof(ListViewItem);
Setter backGroundSetter = new Setter();
backGroundSetter.Property = ListViewItem.BackgroundProperty;
ListView listView =
ItemsControl.ItemsControlFromItemContainer(container)
as ListView;
int index =
listView.ItemContainerGenerator.IndexFromContainer(container);
if (index % 2 == 0) <-- here your own criteria
{
backGroundSetter.Value = Brushes.LightBlue;
}
else
{
backGroundSetter.Value = Brushes.Beige;
}
st.Setters.Add(backGroundSetter);
return st;
}
}
use of the styleselector
xaml
<ListView
ItemsSource="{Binding Source={StaticResource EmployeeData},
XPath=Employee}"
ItemContainerStyleSelector="{DynamicResource myStyleSelector}" >
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding XPath=FirstName}"
Header="First Name" Width="120"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath=LastName}"
Header="Last Name" Width="120"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath=FavoriteCity}"
Header="Favorite City" Width="120"/>
</GridView>
</ListView.View>
</ListView>

How to get a check-box in grid header

With this application, first column in grid is check box type with its header says Select. I would like the header to show a check box also. Checking/Unchecking that check box should check or uncheck all items in the grid. How can I do that?
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Loaded="Data_Loaded" >
<Grid.RowDefinitions>
<RowDefinition Height="6*" />
<RowDefinition />
</Grid.RowDefinitions>
<DataGrid x:Name="grEmployees" HorizontalAlignment="Left" Margin="10,10,0,0" CanUserAddRows="False" CanUserDeleteRows="False"
VerticalAlignment="Top" AlternatingRowBackground="LightBlue" AlternationCount="2" AutoGenerateColumns="False" Grid.Row="0">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Select" Width="2*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="chkSelectedDevice" IsChecked="{Binding Path=Configure, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Last Name" Binding="{Binding LastName, Mode=OneWay}" Width="3*" />
<DataGridTextColumn Header="First Name" Binding="{Binding FirstName, Mode=OneWay}" Width="2*" />
<DataGridTextColumn Header="Description" Binding="{Binding Description, Mode=OneWay}" Width="5*" />
</DataGrid.Columns>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="5" Grid.Row="1" >
<Button x:Name="btnClose" Content="Close" Margin="5" Width="50" />
</StackPanel>
</Grid>
</Window>
public partial class MainWindow : Window
{
private List<Employee> Employees = null;
public MainWindow()
{
InitializeComponent();
}
private void Data_Loaded(object sender, RoutedEventArgs e)
{
Employees = new List<Employee>()
{
new Employee() { IsHardWorking = false, LastName = "Silly", FirstName = "Dude", Description= "this due is a mess" },
new Employee() { IsHardWorking = true, LastName = "Mean", FirstName = "Person", Description= "funny" },
new Employee() { IsHardWorking = false, LastName = "New", FirstName = "Friend", Description= "let her go in next round of layoffs" },
new Employee() { IsHardWorking = true, LastName = "My", FirstName = "Buddy", Description= "simply no comments" },
};
this.grEmployees.ItemsSource = Employees;
}
}
Right, so luckily there's nifty built in ways to customize all sorts of things. In this case we'll just override the default column header template with our own and plop a CheckBox in there.
<DataGridTemplateColumn.Header>
<CheckBox Name="ACheckBox"
Checked="Do_Something"
Unchecked="Do_Something_Else"/>
</DataGridTemplateColumn.Header>
Hope this helps. Cheers
<Grid Loaded="Data_Loaded" >
<Grid.RowDefinitions>
<RowDefinition Height="6*" />
<RowDefinition />
</Grid.RowDefinitions>
<DataGrid x:Name="grEmployees" HorizontalAlignment="Left" Margin="10,10,0,0" CanUserAddRows="False" CanUserDeleteRows="False"
VerticalAlignment="Top" AlternatingRowBackground="LightBlue" AlternationCount="2" AutoGenerateColumns="False" Grid.Row="0">
<DataGrid.Columns>
<DataGridTextColumn>
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<CheckBox></CheckBox>
<TextBlock>Test</TextBlock>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTemplateColumn Header="Select" Width="2*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="chkSelectedDevice" IsChecked="{Binding Path=Configure, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Last Name" Binding="{Binding LastName, Mode=OneWay}" Width="3*" />
<DataGridTextColumn Header="First Name" Binding="{Binding FirstName, Mode=OneWay}" Width="2*" />
<DataGridTextColumn Header="Description" Binding="{Binding Description, Mode=OneWay}" Width="5*" />
</DataGrid.Columns>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="5" Grid.Row="1" >
<Button x:Name="btnClose" Content="Close" Margin="5" Width="50" />
</StackPanel>
</DataGrid>
</Grid>

Getting selected Item in DataGrid in WPF

I have a datagrid and textboxes. When I select a row in DataGrid I want the textboxes to be filled with related data of that datagrid column. Here is the picture.,
I have written this code in MainWindow.xaml.cs :
private void personelEntityDataGrid_Loaded(object sender, RoutedEventArgs e)
{
PersonelEntity pers = (PersonelEntity)personelEntityDataGrid.SelectedItem;
NameBox.Text = pers.Name; // I get exception here
AgeBox.Text = pers.Age.ToString();
PhoneNumberBox.Text = pers.PhoneNumber;
AddresBox.Text = pers.Address;
}
When I run the code I get the null reference exception in the line that I wrote. Here is the exception:
{"Object reference not set to an instance of an object."}
I guess the object pers is null. Can you tell me how to make this work?
Here is my xaml file :
<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" xmlns:local="clr-namespace:Personel" mc:Ignorable="d" x:Class="Personel.MainWindow"
Title="MainWindow" Height="500" Width="725" Loaded="Window_Loaded">
<Window.Resources>
<CollectionViewSource x:Key="personelEntityViewSource" d:DesignSource="{d:DesignInstance {x:Type local:PersonelEntity}, CreateList=True}"/>
</Window.Resources>
<Grid DataContext="{StaticResource personelEntityViewSource}" >
<Label Content="Personnel
" HorizontalAlignment="Left" Margin="55,47,0,0" VerticalAlignment="Top"/>
<Button Content="Delete" HorizontalAlignment="Left" Margin="344,47,0,0" VerticalAlignment="Top" Width="75" Click="Delete_Button_Click"/>
<Button Content="Add" HorizontalAlignment="Left" Margin="477,47,0,0" VerticalAlignment="Top" Width="75" Click="Add_Button_Click"/>
<Button Content="Update" HorizontalAlignment="Left" Margin="624,47,0,0" VerticalAlignment="Top" Width="75" Click="Update_Button_Click"/>
<Label Content="Name" HorizontalAlignment="Left" Margin="55,91,0,0" VerticalAlignment="Top"/>
<Label Content="Age" HorizontalAlignment="Left" Margin="55,132,0,0" VerticalAlignment="Top"/>
<Label Content="Phone Number" HorizontalAlignment="Left" Margin="55,178,0,0" VerticalAlignment="Top"/>
<Label Content="Address" HorizontalAlignment="Left" Margin="55,218,0,0" VerticalAlignment="Top"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="309,95,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="367" Name="NameBox"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="309,136,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="57" Name="AgeBox"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="309,178,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120" Name="PhoneNumberBox"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="309,222,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="367" Name="AddresBox"/>
<DataGrid x:Name="personelEntityDataGrid" AutoGenerateColumns="False" SelectionChanged="personelEntityDataGrid_SelectionChanged" EnableRowVirtualization="True" ItemsSource="{Binding Path=.}" Margin="10,291,0,-22" RowDetailsVisibilityMode="VisibleWhenSelected" Loaded="personelEntityDataGrid_Loaded">
<DataGrid.Columns>
<DataGridTextColumn x:Name="addressColumn" Binding="{Binding Address}" Header="Address" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="ageColumn" Binding="{Binding Age}" Header="Age" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="idColumn" Binding="{Binding Id}" Header="Id" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="nameColumn" Binding="{Binding Name}" Header="Name" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="phoneNumberColumn" Binding="{Binding PhoneNumber}" Header="Phone Number" Width="SizeToHeader"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Don't check in Loaded event, instead Check in selectionChanged event, also add a null check to your pers object
private void personelEntityDataGrid_SelectionChanged(object sender, RoutedEventArgs e)
{
PersonelEntity pers = (PersonelEntity)personelEntityDataGrid.SelectedItem;
if(pers != null)
{
NameBox.Text = pers.Name; // I get exception here
AgeBox.Text = pers.Age.ToString();
PhoneNumberBox.Text = pers.PhoneNumber;
AddresBox.Text = pers.Address;
}
}
Here's how you could do it with bindings. The "Text" parameter of each textbox should be modified thusly:
Text = "{Binding ElementName = personelEntityDataGrid, Path = CurrentItem.<FIELD_NAME_HERE>}"
so for the nameBox, you would have:
Text = "{Binding ElementName = personelEntityDataGrid, Path = CurrentItem.Name}"

Categories

Resources