Click here to Skip to main content
15,439,373 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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:

XML
<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

C#
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?
Posted
Comments
Gerry Schmitz 3-Jul-22 12:05pm    
Selecting a new row would at least have to trigger a property changed event for the text boxes ... and I don't see any (selection changed handlers).
Member 12692000 3-Jul-22 12:13pm    
How would you do that, can you show please?
Gerry Schmitz 3-Jul-22 12:28pm     CRLF
I'm not a MVVM (at all costs) fan, so don't ask me for the "MVVM version". https://stackoverflow.com/questions/29138814/how-to-get-datagrid-selected-row-value-in-textbox
Member 12692000 3-Jul-22 20:59pm     CRLF
I'm not a MVVM(at all costs) fan either but I've been told in many online forums that if I want to properly utilize the full benefits of bindings and update the UI when database data changes then MVVM is the way to go, so here I am. Personally I do find the MVVM pattern overly convoluted in my simple app but I don't know what I should do.
Member 12692000 4-Jul-22 6:25am    
Anyways, your 1st reply solved the problem, thanks

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900