Click here to Skip to main content
15,881,204 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello!

I am very confused.

I am building a WPF application, trying to use the MVVM design pattern. It's fascinating and rewarding, even though it seems overly complex at times. I am new to programming, and I've only really dabbled in WinForms before this.

I've been through so many changes and adaptations, by experimenting and trying to implement solutions people provide me with, that I've sort of lost grip of everything I feel.

My application consists of the following (I am going to be thorough, because not being thorough is what got me into trouble in the first place):

ViewModels:
BaseViewModel.cs
MainViewModel.cs
AddViewModel.cs

Models:
ConnectionString.cs
LicenseHolder.cs
UserInfo.cs

Views:
HomeWindow.xaml
LicenseHolderProfileWindow.xaml
LicenseHoldersWindow.xaml
LoginScreenWindow.xaml
NewLicenseHolderWindow.xaml

Application flow:
LoginScreen is naturally the first window that opens, once you log in, you end up at the HomeWindow, which is basically just buttons leading to the different parts of the application (which only one of those is under development at the moment). I click a button to go to the LicenseHoldersWindow, which contains a DataGrid. The DataGrid is populated by a SQL server table, bound to an ObservableCollection. And here is where the tomfoolery begins.
See, at the moment, I just want to do a few simple things, which was fairly easy to get to work in WinForms, but proving quite the challenge in WPF.

Firstly: I want the DataGrid to automatically get the data from the server without having to press a button of any sort. This currently works.

Secondly: I want to be able to delete rows by clicking a button. This currently works.

Thirdly: I want to be able to add rows, by clicking a button -> opening a new window (NewLicenseHolderWindow) -> filling out TextBoxes, clicking a save button (window closes) -> voilà - DataGrid is updated! **THIS DOES NOT WORK**.
If I want the new row to appear in the DataGrid, I have to re-open the window.
This angers me tremendously.

Fourthly(?): I also tried implementing the function to select a DataGrid row, clicking a button -> opening a new window (LicenseHolderProfileWindow), and have the TextBoxes therein be populated by the data in the selected row. This kind of doesn't work.
Most of the TextBoxes are populated as they should, but some are missing, and some are misplaced.
Injustice! Definitively some issues with DataBinding, but I have been unsuccessful in finding out just what. They all seem to be bound the same, with no typos, yet only some of them come out right. Specifically: "Foretaksnavn", "Foretaksnr.", "Adresse", "Poststed", "Postnr", "BIC", "IBAN come out correctly. The textboxes are filled as they should. "Kontonr." is given the value of "Tlf", "Kontakt" is left empty, "Tlf." is given the value of "Epost", and "Epost" is given the value of "Kontakt".
That is so odd to me.

I am going to post most of my code, and am very grateful for any who read it all and try to understand it.

In addition to the specific issues I've listed, I am also very interested in streamlining my application. I want it to fully adhere to the MVVM design pattern. I want it to be slim, not bulky, I want it to be as petite as it possibly can be. I feel like I am using far to much code-lines, and to many .cs files. Isn't it possible to just use one ViewModel? As you will see in my code below, my ConnectionString, and some arbritary code to drag the entered UserName with me to correctly label the logout tag, which is the users e-mail address. I feel like that's not correctly done. Also, the LoginScreen.xaml is not built up correctly, I am aware of this, but I don't want to overstay my welcome - it's a issue I'll handle another day (but by all means, if anyone is feeling adventurous, I'll accept any pointers regarding that one aswell).

My code follows.

Models


--> ConnectionString.cs - just my connection string...

--> LicenseHolder.cs - my holder class, the getters/setters for the DataGrid columns.

C#
namespace Ridel.Hub.Model {
    public class LicenseHolder {
        public int ID { get; set; }
        public string Foretaksnavn { get; set; }
        public string Foretaksnummer { get; set; }
        public string Adresse { get; set; }
        public int Postnummer { get; set; }
        public string Poststed { get; set; }
        public string BIC { get; set; }
        public string IBAN { get; set; }
        public string Kontakt { get; set; }
        public string Epost { get; set; }
        public string Tlf { get; set; }
        public string Kontonummer { get; set; }
    }
}


UserInfo.cs - simple class to bring with me the e-mail address of the logged in user to fill a label used as a 'Log out'-button.

C#
namespace Ridel.Hub {
    public class UserInfo {
        private const string userNameString = "";
        public static string UserName { get; set; } = userNameString;
    }
}


ViewModels

--> MainViewModel

C#
using System;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Windows;
using GalaSoft.MvvmLight.CommandWpf;
using Ridel.Hub.Model;
namespace Ridel.Hub.ViewModel {
    public class MainViewModel : AddViewModel, INotifyPropertyChanged {
        public MainViewModel() {
            FillDataGridLicenseHolders();
        }
        // This method triggers when the user clicks the log out button (which is their e-mail address)
        public static void CloseAllWindowsExceptLoginScreen() {
            Application.Current.Windows
                .Cast<Window>()
                .Where(w => w is not LoginScreenWindow)
                .ToList()
                .ForEach(w => w.Close());

            MainViewModel viewModel = new MainViewModel();
            LoginScreenWindow loginScreen = new LoginScreenWindow(viewModel);
            loginScreen.Show();
        }
        public void FillDataGridLicenseHolders() {
            try {
                using (SqlConnection sqlCon = new(ConnectionString.connectionString))
               using (SqlCommand sqlCmd = new("select * from tblLicenseHolder", sqlCon))
                using (SqlDataAdapter sqlDaAd = new(sqlCmd))
                using (DataSet ds = new()) {
                    sqlCon.Open();
                    sqlDaAd.Fill(ds, "tblLicenseHolder");
                    foreach (DataRow dr in ds.Tables[0].Rows) {
                        // Adding the rows in the DataGrid to the ObservableCollection
                        LicenseHolders.Add(new LicenseHolder {
                            ID = Convert.ToInt32(dr[0].ToString()),
                            Foretaksnavn = dr[1].ToString(),
                            Foretaksnummer = dr[2].ToString(),
                            Adresse = dr[3].ToString(),
                            Postnummer = (int)dr[4],
                            Poststed = dr[5].ToString(),
                            BIC = dr[6].ToString(),
                            IBAN = dr[7].ToString(),
                            Kontakt = dr[8].ToString(),
                            Epost = dr[9].ToString(),
                            Tlf = dr[10].ToString(),
                            Kontonummer = dr[11].ToString()
                        });
                    }
                }
            } catch (Exception ex) {
                MessageBox.Show(ex.Message, "Message", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }
        private static bool RemoveFromDB(LicenseHolder myLicenseHolder) {
            string sqlString = $"Delete from tblLicenseHolder where ID = '{myLicenseHolder.ID}'";
            if (MessageBox.Show("Er du sikker på at du ønsker å slette valgt løyvehaver?", "Slett løyvehaver", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes) {
                try {
                    using (SqlConnection sqlCon = new(ConnectionString.connectionString))
                    using (SqlCommand sqlCmd = new(sqlString, sqlCon)) {

                        sqlCon.Open();
                        sqlCmd.ExecuteNonQuery();
                        return true;
                    }
                }
                catch {
                    return false;
                }
            } else {
                return false;
            }
        }
        private void RemoveLicenseHolderExecute(LicenseHolder myLicenseHolder) {
            bool result = RemoveFromDB(myLicenseHolder);
            if (result)
                LicenseHolders.Remove(myLicenseHolder);
        }
        private RelayCommand<LicenseHolder> _removeLicenseHoldersCommand;
        public RelayCommand<LicenseHolder> RemoveLicenseHoldersCommand => _removeLicenseHoldersCommand
            ??= new RelayCommand<LicenseHolder>(RemoveLicenseHolderExecute, RemoveLicenseHolderCanExecute);
        private bool RemoveLicenseHolderCanExecute(LicenseHolder myLicenseHolder) {
            return LicenseHolders.Contains(myLicenseHolder);
        }   
    }
}


--> AddViewModel (this is newly added, based on some feed-back I got, and it was at this point I felt things really got out of hand

C#
using System;
using System.Collections.ObjectModel;
using System.Data.SqlClient;
using System.Windows;
using System.Windows.Input;
using GalaSoft.MvvmLight.CommandWpf;
using Ridel.Hub.Model;
namespace Ridel.Hub.ViewModel {
    public class AddViewModel : BaseViewModel {
        public ObservableCollection<LicenseHolder> LicenseHolders { get; set; }
        public ICommand RefreshCommand { get; private set; }
        public AddViewModel() {
            RefreshCommand = new RelayCommand(this.ExecuteRefreshCommand);
            LicenseHolders = new ObservableCollection<LicenseHolder>();
        }
        private string _foretaksnavn;
        public string Foretaksnavn {

            get { return _foretaksnavn; }
            set { SetValue(ref _foretaksnavn, value); }
        }

        private string _foretaksnummer;
        public string Foretaksnummer {

            get { return _foretaksnummer; }
            set { SetValue(ref _foretaksnummer, value); }
        }

        private string _adresse;
        public string Adresse {

            get { return _adresse; }
            set { SetValue(ref _adresse, value); }
        }

        private int _postnummer;
        public int Postnummer {

            get { return _postnummer; }
            set { SetValue(ref _postnummer, value); }
        }

        private string _poststed;
        public string Poststed {

            get { return _poststed; }
            set { SetValue(ref _poststed, value); }
        }

        private string _bic;
        public string BIC {

            get { return _bic; }
            set { SetValue(ref _bic, value); }
        }

        private string _iban;
        public string IBAN {

            get { return _iban; }
            set { SetValue(ref _iban, value); }
        }

        private string _kontakt;
        public string Kontakt {

            get { return _kontakt; }
            set { SetValue(ref _kontakt, value); }
        }

        private string _epost;
        public string Epost {

            get { return _epost; }
            set { SetValue(ref _epost, value); }
        }

        private string _tlf;
        public string Tlf {

            get { return _tlf; }
            set { SetValue(ref _tlf, value); }
        }

        private string _kontonummer;
        public string Kontonummer {

            get { return _kontonummer; }
            set { SetValue(ref _kontonummer, value); }
        }

        private void ExecuteRefreshCommand() {

            string sqlString = "insert into tblLicenseHolder (Foretaksnavn, Foretaksnummer, Adresse, Postnummer, Poststed, BIC, IBAN, Kontakt, Epost, Tlf, Kontonummer) " +
                "values (@Foretaksnavn, @Foretaksnummer, @Adresse, @Postnummer, @Poststed, @BIC, @IBAN, @Kontakt, @Epost, @Tlf, @Kontonummer)";

            if (Foretaksnavn == null || Foretaksnummer == null || Adresse == null 
                || Postnummer == 0 || Poststed == null || BIC == null || IBAN == null 
                || Kontakt == null || Epost == null || Tlf == null || Kontonummer == null) {

                MessageBox.Show("Fyll ut alle feltene.");

            } else {

                LicenseHolders = new ObservableCollection<LicenseHolder>();
                LicenseHolders.Add(new LicenseHolder() { Foretaksnavn = "Foretaksnavn" });
                LicenseHolders.Add(new LicenseHolder() { Foretaksnummer = "Foretaksnummer" });
                LicenseHolders.Add(new LicenseHolder() { Adresse = "Adresse" });
                LicenseHolders.Add(new LicenseHolder() { Postnummer = Postnummer });
                LicenseHolders.Add(new LicenseHolder() { Poststed = "Poststed" });
                LicenseHolders.Add(new LicenseHolder() { BIC = "BIC" });
                LicenseHolders.Add(new LicenseHolder() { IBAN = "IBAN" });
                LicenseHolders.Add(new LicenseHolder() { Kontakt = "Kontakt" });
                LicenseHolders.Add(new LicenseHolder() { Epost = "Epost" });
                LicenseHolders.Add(new LicenseHolder() { Tlf = "Tlf" });
                LicenseHolders.Add(new LicenseHolder() { Kontonummer = "Kontonummer" });

                try {

                    using (SqlConnection sqlCon = new(ConnectionString.connectionString))
                    using (SqlCommand sqlCmd = new(sqlString, sqlCon)) {

                        sqlCon.Open();
                        sqlCmd.Parameters.AddWithValue("@Foretaksnavn", Foretaksnavn.ToString());
                        sqlCmd.Parameters.AddWithValue("@Foretaksnummer", Foretaksnummer.ToString());
                        sqlCmd.Parameters.AddWithValue("@Adresse", Adresse.ToString());
                        sqlCmd.Parameters.AddWithValue("@Postnummer", Convert.ToInt32(Postnummer.ToString()));
                        sqlCmd.Parameters.AddWithValue("@Poststed", Poststed.ToString());
                        sqlCmd.Parameters.AddWithValue("@BIC", BIC.ToString());
                        sqlCmd.Parameters.AddWithValue("@IBAN", IBAN.ToString());
                        sqlCmd.Parameters.AddWithValue("@Kontakt", Kontakt.ToString());
                        sqlCmd.Parameters.AddWithValue("@Epost", Epost.ToString());
                        sqlCmd.Parameters.AddWithValue("@Tlf", Tlf.ToString());
                        sqlCmd.Parameters.AddWithValue("@Kontonummer", Kontonummer.ToString());
                        sqlCmd.ExecuteNonQuery();
                        MessageBox.Show("Ny løyvehaver lagret.");
                    }
                }
                catch (Exception ex) {

                    MessageBox.Show(ex.Message, "Message", MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }
        }
    }
}


I am especially uncertain about how I've strutured the ExecuteRefreshCommand()-method.
The addition to the server is no problem, but adding to the ObservableCollection is not happening. Hopefully, there is a way to simplify and compact those two tasks into one: add to server & update ObservableCollection (do I need to add each item?!). Also, the getters/setters strings seems redundant, can't I get and set what I need using the LicenseHolder.cs model class`?

->BaseViewModel

”C#”
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Ridel.Hub.ViewModel {

    public abstract class BaseViewModel : 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 bool SetValue<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) {

            if (Equals(storage, value)) return false;

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }
    }
}
<pre>

</big>Views</big>

I will omit the Windows which are irrelevant (at least to my understanding).
I am only posting the code-behind and the XAML from LicenseHoldersWindow, NewLicenseHolderWindow and LicenseHolderProfileWindow. I'll trim away some of the XAML to make it somewhat readable.

--> LicenseHoldersWindow

<pre lang="XAML">
<Window
    x:Class="Ridel.Hub.LicenseHoldersWindow"
    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:local="clr-namespace:Ridel.Hub"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:viewmodel="clr-namespace:Ridel.Hub.ViewModel" d:DataContext="{d:DesignInstance Type=viewmodel:MainViewModel}"
    ShowInTaskbar="False"
    mc:Ignorable="d">

    <Canvas Margin="10,10,10,10">

        <Button
            x:Name="btnLogOut"
            Click="btnLogOut_Click"
            Content="LoggedInUser"
            Style="{DynamicResource ButtonWithOnlyText}" />

        <Button
            x:Name="btnProfile"
            Background="#48bb88"
            Content="Open profile"
            Style="{DynamicResource ButtonWithRoundCornersGreen}"
            Visibility="Visible" Click="btnProfile_Click" />

        <Button
            x:Name="btnNew"     
            Click="btnNew_Click"
            Content="New licenseholder"
            Style="{DynamicResource ButtonWithRoundCornersGreen}" />

        <Button
            x:Name="btnDelete"
            Command="{Binding RemoveLicenseHoldersCommand}"
            CommandParameter="{Binding SelectedItem, ElementName=dgLicenseHolder}"
            Content="Delete licenseholder"
            Style="{DynamicResource ButtonWithRoundCornersGreen}" />

        <DataGrid
            x:Name="dgLicenseHolder"
            CanUserAddRows="False"
            CanUserDeleteRows="False"
            IsReadOnly="True"
            SelectionChanged="dgLicenseHolder_SelectionChanged"
            ItemsSource="{Binding LicenseHolders}"
            SelectionMode="Single">

            <DataGrid.Columns>
                <DataGridTextColumn
                    Binding="{Binding Path=ID}"
                    Header="ID"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Width="310"
                    Binding="{Binding Path=Foretaksnavn}"
                    Header="Foretaksnavn"
                    HeaderStyle="{StaticResource CenterGridHeaderStyle}"
                    IsReadOnly="True"
                    Visibility="Visible" />
                <DataGridTextColumn
                    Binding="{Binding Path=Foretaksnummer}"
                    Header="Foretaksnummer"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Adresse}"
                    Header="Adresse"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Postnummer}"
                    Header="Postnummer"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Width="*"
                    Binding="{Binding Path=Poststed}"
                    Header="Poststed"
                    HeaderStyle="{StaticResource CenterGridHeaderStyle}"
                    IsReadOnly="True"
                    Visibility="Visible" />
                <DataGridTextColumn
                    Binding="{Binding Path=BIC}"
                    Header="BIC"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=IBAN}"
                    Header="IBAN"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Kontakt}"
                    Header="Kontakt"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Epost}"
                    Header="Epost"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Tlf}"
                    Header="Tlf"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
                <DataGridTextColumn
                    Binding="{Binding Path=Kontonummer}"
                    Header="Kontonummer"
                    IsReadOnly="True"
                    Visibility="Collapsed" />
            </DataGrid.Columns>
        </DataGrid>
    </Canvas>
</Window>




C#
using System.Windows;
using System.Windows.Controls;
using Ridel.Hub.ViewModel;

namespace Ridel.Hub {

    public partial class LicenseHoldersWindow : Window {

        public LicenseHoldersWindow(MainViewModel viewModel) {

            InitializeComponent();
            btnLogOut.Content = UserInfo.UserName;
            DataContext = viewModel;
        }

        private void btnLogOut_Click(object sender, RoutedEventArgs e) {

            if (MessageBox.Show("Er du sikker på at du ønsker å logge ut?", "Logg ut", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) {

                MainViewModel.CloseAllWindowsExceptLoginScreen();
            }
        }

        private void dgLicenseHolder_SelectionChanged(object sender, SelectionChangedEventArgs e) {

            btnProfile.IsEnabled = true;
            btnDelete.IsEnabled = true;
        }

        private void btnNew_Click(object sender, RoutedEventArgs e) {

            NewLicenseHolderWindow nlhw = new NewLicenseHolderWindow();
            nlhw.ShowDialog();
        }

        private void btnProfile_Click(object sender, RoutedEventArgs e) {

            if (this.dgLicenseHolder.SelectedItems.Count == 1) {

                LicenseHolderProfileWindow lpw = new LicenseHolderProfileWindow(null) { Owner = this, DataContext = dgLicenseHolder.SelectedItem };
                lpw.ShowDialog();
            }
        }
    }
}


--> NewLicenseHolderWindow

XAML
<Window
    x:Class="Ridel.Hub.NewLicenseHolderWindow"
    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:viewmodel="clr-namespace:Ridel.Hub.ViewModel" d:DataContext="{d:DesignInstance Type=viewmodel:AddViewModel}"
    ResizeMode="NoResize"
    ShowInTaskbar="False"
    mc:Ignorable="d">

    <Canvas Margin="10,10,42,10">
        <Button
            Name="btnLogOut"
            Click="btnLogOut_Click"
            Content="LoggedInUser"
            Style="{DynamicResource ButtonWithOnlyText}" />
   
        <TextBox
            Name="txtKontakt"
            Text="{Binding Path=Kontakt}"/>
        <TextBox
            Name="txtTlf"
            Text="{Binding Path=Tlf}"/>
        <TextBox
            Name="txtEpost"
            Text="{Binding Path=Epost}"/>
        <TextBox
            Name="txtForetaksnavn"
            Text="{Binding Path=Foretaksnavn}" />
        <TextBox
            Name="txtForetaksnr"
            Text="{Binding Path=Foretaksnummer}"/>
        <TextBox
            Name="txtAdresse"
            Text="{Binding Path=Adresse}"/>
        <TextBox
            Name="txtPoststed"
            Text="{Binding Path=Poststed}"/>
        <TextBox
            Name="txtPostnummer"
            Text="{Binding Path=Postnummer}"/>
        <TextBox
            Name="txtBIC"
            Text="{Binding Path=BIC}"/>
        <TextBox
            Name="txtIBAN"
            Text="{Binding Path=IBAN}"/>
        <TextBox
            Name="txtKontonr"
            Text="{Binding Path=Kontonummer}"/>

        <Button
            Name="btnSave"
            Command="{Binding Path=RefreshCommand}"
            Content="Save"
            Style="{DynamicResource ButtonWithRoundCornersGreen}">
        </Button>
    </Canvas>
</Window>



C#
using System.ComponentModel;
using System.Linq;
using System.Windows;
using Ridel.Hub.ViewModel;

namespace Ridel.Hub {

    public partial class NewLicenseHolderWindow : Window, INotifyPropertyChanged {

        public event PropertyChangedEventHandler PropertyChanged;

        public NewLicenseHolderWindow() {

            InitializeComponent();
            btnLogOut.Content = UserInfo.UserName;
        }

        private void btnLogOut_Click(object sender, RoutedEventArgs e) {

            if (MessageBox.Show("Er du sikker på at du ønsker å logge ut?", "Logg ut", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) {

                MainViewModel.CloseAllWindowsExceptLoginScreen();
            }
        }
    }
}


-->LicenseHolderProfileWindow

XAML
<Window
    x:Class="Ridel.Hub.LicenseHolderProfileWindow"
    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:viewmodel="clr-namespace:Ridel.Hub.ViewModel" d:DataContext="{d:DesignInstance Type=viewmodel:AddViewModel}"
    mc:Ignorable="d">

    <Canvas Margin="10,10,42,10">
        <Button
            Name="btnLogOut"
            Click="btnLogOut_Click"
            Content="LoggedInUser"
            Style="{DynamicResource ButtonWithOnlyText}" />

        <TextBox
            Name="txtKontakt"
            Text="{Binding Kontakt, Mode=TwoWay, FallbackValue=Kontakt}" />
        <TextBox
            Name="txtTlf"
            Text="{Binding Tlf, Mode=TwoWay, FallbackValue=Tlf}" />
        <TextBox
            Name="txtEpost"
            Text="{Binding Epost, Mode=TwoWay, FallbackValue=Epost}" />
        <TextBox
            Name="txtForetaksnavn"
            Text="{Binding Foretaksnavn, Mode=TwoWay, FallbackValue=Foretaksnavn}" />
        <TextBox
            Name="txtForetaksnr"
            Text="{Binding Foretaksnummer, Mode=TwoWay, FallbackValue=Foretaksnummer}" />
        <TextBox
            Name="txtAdresse"
            Text="{Binding Adresse, Mode=TwoWay, FallbackValue=Adresse}" />
        <TextBox
            Name="txtPoststed"
            Text="{Binding Poststed, Mode=TwoWay, FallbackValue=Poststed}" />
        <TextBox
            Name="txtPostnummer"  
            Text="{Binding Postnummer, Mode=TwoWay, FallbackValue=Postnummer}" />
        <TextBox
            Name="txtBIC"
            Text="{Binding BIC, Mode=TwoWay, FallbackValue=BIC}" />
        <TextBox
            Name="txtIBAN"
              Text="{Binding IBAN, Mode=TwoWay, FallbackValue=IBAN}" />
        <TextBox
            Name="txtKontonr"
            IsReadOnly="True"
            Text="{Binding Kontonummer, Mode=TwoWay, FallbackValue=Kontonummer}" />

        <Button
            Name="btnLagre"           
            Click="btnLagre_Click"
            Command="{Binding RefreshCommand}"
            Content="Lagre"
            Style="{DynamicResource ButtonWithRoundCornersGreen}" />
     </Canvas>
</Window>



C#
using System.Windows;
using Ridel.Hub.ViewModel;

namespace Ridel.Hub {

    public partial class LicenseHolderProfileWindow : Window {

        public LicenseHolderProfileWindow(AddViewModel viewModel) {

            InitializeComponent();
            DataContext = viewModel;
        }

        private void btnLogOut_Click(object sender, RoutedEventArgs e) {

            if (MessageBox.Show("Er du sikker på at du ønsker å logge ut?", "Logg ut", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) {

                MainViewModel.CloseAllWindowsExceptLoginScreen();
            }
        }

        private void btnSave_Click(object sender, RoutedEventArgs e) {

            btnAllowEdit.IsEnabled = true;
            Close();
        }
    }
}


So, there you have it!

Thankful if anyone read this far, and even more thankful if anyone decides to give me their 2-cents.

What I have tried:

All I do these days is research bugs, and try to implement code I don't fully (or halfly) understand.

I realize going through all this code is work, so 25USD for the most informative answer! =D (PayPal, or Western Union transfer, or international bank transfer).
Posted
Comments
[no name] 25-Jun-21 13:48pm    
Firstly: A "good" place to load a DataGrid is in the Loaded event of the hosting Window (async load of observable collection). Or, you load a static collection during startup, and then connect the DataGrid (again, in the hosting Windows loaded event).

And if "LicenseHolder" is participating in binding, it needs to implement INotifyPropertyChanged.

Thirdly: If you add records (with a form) to an ObservableCollection that is bound to a DataGrid, the new records will show up in the DataGrid.

Fourthly: I don't use MVVM; I think it's pointless unless you think you need a different "view" for every device your code is to run on. The thinking usually goes like this: how do I do this in C# / WPF; then, how do I do it in MVVM? Hard enough when starting out.

Anyway, when you select a record in a DataGrid, it fires the SelectionChanged event, where the SelectedItem is an object you cast to the type that is in your ObservableCollection. Then you can copy to your TextBoxes or set their (view model) DataContext to the SelectedItem.

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