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
.
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.
namespace Ridel.Hub {
public class UserInfo {
private const string userNameString = "";
public static string UserName { get; set; } = userNameString;
}
}
ViewModels
--> MainViewModel
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();
}
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) {
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
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
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>
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
<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>
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
<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>
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).