i'm new to the concept of XAML, WPF, MVVM and so on. And firstly maybe sorry for my bad english skills :P
I have the task to create an application, that takes user inputs. My Mainwindow is an userform with some textboxes, buttons and labels. These textboxes are bound to an instance of the class "Versandauftrag
"(english-> shipping order). In turn, this instance has some properties that are objects from other custom classes like adressee, addressor, advice...
For illustration:
public class Versandauftrag
private UpdateBase? _update; <--- Class for INotifyPropertyChanged
public string? ID {get;set;}
public Empfänger? Empfänger { get; set; } <---- Addressee
public Avis? Avis { get; set; } <---- Advice
public Versender? Versender { get; set; } <--- Addressor
public Abholung? Abholung { get; set; }
public ObservableCollection<Packstück>? PackstückListe { get; set; } <--- List with items
public Packstück? SelectedPackstück { get; set; } = null;
public Versandauftrag()
{
this._update = new UpdateBase();
}
Here the Addresse
class for example:
public class Empfänger : UpdateBase
{
private Address adresse = new Address();
public Address Adresse
{
get { return adresse; }
set
{
if (value != adresse)
{
adresse = value;
OnPropertyChanged();
}
}
}
private string? _referenz;
public string? Referenz...
private string? _kundennr;
public string? Kundennr ...
private bool isPrivate;
public bool IsPrivate ...
My ViewModel
class is Eingabe
(Input).
public class Eingabe : UpdateBase
//some commands
public MainWindow MainWindow { get; set; }
public Versandauftrag Versandauftrag { get; set; }
private string lastJob;
public string LastJob...
public Eingabe(MainWindow main)
{ MainWindow = main;
MainWindow.DataContext = this; <--- this was one attempt to get the real bounded instance
Versandauftrag = new Versandauftrag{ Empfänger = new Empfänger { Referenz = "123"}
};
MainWindow:
public partial class MainWindow : Window
public Eingabe EingabeVM { get; set; }
public MainWindow()
{
InitializeComponent();
DataBaseConnection.initDB();
EingabeVM = new Eingabe(this);
this.btnVersenden.Click += EingabeVM.VersendenButton_Click;
this.txtNameVersender.SelectionChanged += EingabeVM.txtNameVersender_SelectionChanged;
this.btnNeu.Click += EingabeVM.neuButton_Click;
}
XAML Textbox example:
<TextBox x:Name="txtPLZ" Text="{Binding Path=Versandauftrag.Empfänger.Adresse.Zip , UpdateSourceTrigger=PropertyChanged}" Width="54" FontSize="16" />
I set the DataContext from MainWindow
at the initalitation from Eingabe
(in the constructor). On the MainWindow is a button "New" that open a new form which fetches the relevant data from a database. This data fills every property from Versandauftrag
(all in the right place and order). This all happens in the class EingabeView
which has a property from Eingabe
. The constructor from EingabeView
takes an instance from Eingabe
to set it to its private property from type Eingabe
. After the initialization it sets all the fetched data to the instance <EingabeProperty>.Versandauftrag.x
.
My mainwindow should show all fetched data in the textboxes but it doesn't show any data. I guess that the bindings are not bound to the correct instance of Versandauftrag
but i don't get the right way to handle it.
I've tried the following steps:
Window.DataContext
in XAML -> It show's me that Eingabe
doesn't have an public constructorEdit: Some pictures from the app
MainWindow at the start of the app and also after I press the "Prüfen" (check for shipping id) Button from EingabeView
(the little pic under the button "Neu")
Every single property in your binding chain needs to be observable if it has a setter. You missed this one:
public Versandauftrag Versandauftrag { get; set; }
Versandauftrag = new Versandauftrag{ Empfänger = new Empfänger { Referenz = "123"}
As well as every property of Versandauftrag
(your naming convention is atrocious, you're designing software, not writing a diary). If you can set it, it needs to be observable.
Which also raises the point that maybe not everything should be settable. A proper design would be as immutable as possible, especially with trivially immutable properties like Versandauftrag.PackstückListe
-- it's already an observable collection, setting it is bad design, just call Clear()
on it if needed.