I'm trying to show the column values of the selected row of a wpf datagrid to different textboxes without breaking the mvvm pattern. I'm relatively new to the mvvm.
Here is my XAML:
<DataGrid ItemsSource="{Binding AllBills}" SelectedItem="{Binding SelectedBill, Mode=TwoWay}"
AutoGenerateColumns="False"
HeadersVisibility="Column"
IsReadOnly="True"
CanUserAddRows="False"
SelectionUnit="FullRow"
x:Name="dg">
<DataGrid.Columns>
<DataGridTextColumn
Header="Vendor"
Binding="{Binding Path=Party, Mode=OneWay}"
Width="275"
IsReadOnly="True" />
<DataGridTextColumn
Header="Bill No."
Binding="{Binding Path=BillNo, Mode=OneWay}"
Width="275"
IsReadOnly="True" />
...
</DataGrid.Columns>
</DataGrid>
<GroupBox Header="Bill Data" Margin="10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label FontSize="18" Content="Bill No." HorizontalAlignment="Left" Foreground="Aqua"
VerticalContentAlignment="Center" Grid.Column="0" Grid.Row="0"/>
<TextBox Grid.Row="0" Grid.Column="1" x:Name="tbBillNo" Height="27"
Text="{Binding SelectedBill.BillNo, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5" Width="300" HorizontalAlignment="Left"/>
<Label FontSize="18" Content="Bill Date" HorizontalAlignment="Left" VerticalContentAlignment="Center" Foreground="Aqua"
Grid.Row="1" Grid.Column="0"/>
<TextBox Grid.Row="1" Grid.Column="1" x:Name="tbBillDt" Height="27"
Text="{Binding SelectedBill.BillDt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5" Width="120" HorizontalAlignment="Left"/>
...
<Button FontSize="15" Margin="5" Width="70" Grid.Column="0" Grid.Row="5" Content="Add"/>
<Button FontSize="15" Margin="5" Width="80" Grid.Column="1" Grid.Row="5" Content="Edit"/>
<Button FontSize="15" Margin="5" Width="80" Grid.Column="2" Grid.Row="5" Content="Save"/>
<Button FontSize="15" Margin="5" Width="80" Grid.Column="3" Grid.Row="5" Content="Delete"/>
</Grid>
</GroupBox>
What I have tried:
Also the cs files
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new BillsViewModel();
}
}
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void SetValue<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
field = value;
OnPropertyChanged(propertyName);
}
}
public class Bills : ViewModelBase
{
private int _id;
public int Id
{
get
{
return _id;
}
set
{
SetValue(ref _id, value);
}
}
private string _party;
public string Party
{
get
{
return _party;
}
set
{
SetValue(ref _party, value);
}
}
private string _billNo;
public string BillNo
{
get
{
return _billNo;
}
set
{
SetValue(ref _billNo, value);
}
}
private string _billDt;
public string BillDt
{
get
{
return _billDt;
}
set
{
SetValue(ref _billDt, value);
}
}
...
}
public class Model
{
private List<Bills> _sBills;
public List<Bills> SBills
{
get
{
if (_sBills == null) LoadAllBillsFromDatabase();
return _sBills;
}
}
public void LoadAllBillsFromDatabase()
{
SQLiteConnection m_dbConnection = new SQLiteConnection(@"Data Source=Bills.db;");
SQLiteCommand sqlCom = new SQLiteCommand(@"Select * From billdata", m_dbConnection);
SQLiteDataAdapter sda = new SQLiteDataAdapter(sqlCom);
DataTable dt = new DataTable();
sda.Fill(dt);
_sBills = new List<Bills>();
foreach (DataRow row in dt.Rows)
{
_sBills.Add(new Bills()
{
Id = Convert.ToInt32(row["Id"]),
Party = (string)row["Party"],
BillNo = (string)row["BillNo"],
BillDt = (string)(row["BillDt"]),
Amt = (string)row["Amt"],
DueDt = (string)(row["DueDt"]),
PaidOn = (string)(row["PaidOn"])
});
}
m_dbConnection.Close();
}
}
public class BillsViewModel : ViewModelBase
{
private Bills _SelectedBill;
private ObservableCollection<Bills> _Products;
public ObservableCollection<Bills> Products
{
get { return _Products; }
set { _Products = value; }
}
public Bills SelectedBill
{
get { return _SelectedBill; }
set { _SelectedBill = value; }
}
private List<Bills> _allBills;
public BillsViewModel()
{
Products = new ObservableCollection<Bills>();
_allBills = m.SBills;
AllBills = new ListCollectionView(_allBills)
{
Filter = o => ((Bills)o).Party == SelectedCBItem
};
}
Model m = new Model();
private ICollectionView _allBillsCollection;
public ICollectionView AllBills
{
get { return _allBillsCollection; }
set
{
_allBillsCollection = value;
SetValue(ref _allBillsCollection, value);
}
}
}
SelectedCBItem
is the selected item of a combo box using which the database data is filtered and then displayed on the datagrid .
But when I select a row from the datagrid, it does not show the column values in the text boxes in the group box. What am I missing and how do I make it work?