-
Still loving the framework! I've a DataGrid bound to an BindableCollection, which works nicely: But when I try to add a new row (using TextBoxes in a child-window), I'm causing a mess. It doesn't automatically update, and requires me to re-open the window. using (SqlConnection sqlCon = new(ConnectionString.connectionString))
using (SqlCommand sqlCmd = new(sqlString, sqlCon)) {
sqlCon.Open();
AddLicenseHolderView view = Application.Current.Windows.OfType<AddLicenseHolderView>().FirstOrDefault();
sqlCmd.Parameters.AddWithValue("@Foretaksnavn", view.txtForetaksnavn.Text.ToString());
sqlCmd.Parameters.AddWithValue("@Foretaksnummer", view.txtForetaksnr.Text.ToString());
sqlCmd.Parameters.AddWithValue("@Adresse", view.txtAdresse.Text.ToString());
sqlCmd.Parameters.AddWithValue("@Postnummer", view.txtPostnummer.Text.ToString());
sqlCmd.Parameters.AddWithValue("@Poststed", view.txtPoststed.Text.ToString());
sqlCmd.Parameters.AddWithValue("@BIC", view.txtBIC.Text.ToString());
sqlCmd.Parameters.AddWithValue("@IBAN", view.txtIBAN.Text.ToString());
sqlCmd.Parameters.AddWithValue("@Kontakt", view.txtKontakt.Text.ToString());
sqlCmd.Parameters.AddWithValue("@Epost", view.txtEpost.Text.ToString());
sqlCmd.Parameters.AddWithValue("@Tlf", view.txtTlf.Text.ToString());
sqlCmd.Parameters.AddWithValue("@Kontonummer", view.txtKontonr.Text.ToString());
sqlCmd.ExecuteNonQuery();
}
this.RequestClose(true);
LicenseHolders.AddRange();
NotifyOfPropertyChange(() => LicenseHolders);
LicenseHolders.Refresh(); As you see, I instantiate the View, in order to get the TextBox values, which is not MVVM friendly, and also, doesn't work, for some reason....... I've bound this method to a button in the child-window using your 's:Action' LicenseHolders = new BindableCollection<LicenseHolder>(); The TextBoxes in the child-window is bound like so: Text="{Binding Path=Foretaksnavn}" Where "Foretaksnavn" is one of the strings I have in my I'm guessing this last part is where I wrong? I'm thinking I need something like this: private string _name;
public string Name
{
get { return _name; }
set { SetValue(ref _name, value); }
} in the child-windows ViewModel, but I couldn't get that to work. How would I get the value of the TextBoxes in a ViewModel-first friendly approach? Any tips to get my thinking straightened would be most welcome! |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 6 replies
-
"child-window" is the
You're not passing anything to
Presumably you have a property called I'm afraid there are many parts to this, and you're only showing a little snippet, so it's hard for me to work out what you're even trying to describe. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Thanks, that's made the context clearer. So, I think there are two parts to your question?
The code you've shared doesn't cover either of these: you don't show the code in Can you please post the full code of both the
public class Item : PropertyChangedBase
{
private string _name;
public string Name
{
get => _name;
set => SetAndNotify(ref _name, value);
}
}
public class Parent : PropertyChangedBase
{
private BindableCollection<Item> _items;
public BindableCollection<Item> Items
{
get => _items;
set => SetAndNotify(ref _items, value);
}
public void Test()
{
// Parent.PropertyChanged is fired, for property "Items"
Items = new BindableCollection<Item>();
// BindableCollection<Item>.CollectionChanged is fired
Items.Add(new Item());
// Item.PropertyChanged is fired, for property "Name"
Items[0].Name = "Foo";
}
} |
Beta Was this translation helpful? Give feedback.
-
Just stop and take a step back, please. You're making seemingly random changes, before I've even had a chance to catch up with the load of code you dumped on me previously. Let's just simplify this a bit. You've got:
When the user clicks a button in LicenseHolderView, we show AddView. When they add a new license holder with AddView, we update the DataGrid. Does that sound about right? We've got a choice as to where we do the insertion into the database: in LicenseHolderView or in AddView. Let's do it in AddView, but either would work. We'll then need a way for AddView to signal to LicenseHolderView that it's added a new license holder, and that it should update its list: let's simply use the DialogResult, true if we added a new license holder, false if we didn't. So, a cut-down version: public class LicenseHolderViewModel
{
private readonly IWindowManager windowManager;
public BindableCollection<LicenseHolder> LicenseHolders { get; } = new();
public void LoadLicenseHolders()
{
LicenseHolders.Clear();
// SQL, etc, etc
foreach (...)
{
LicenseHolders.Add(new LicenseHolder(...));
}
}
public void ShowAdd()
{
bool? result = windowManager.ShowDialog(new AddLicenseViewModel(...));
if (result == true)
{
// We added a new license holder: reload our list
LoadLicenseHolders();
}
}
} public class AddViewModel : Screen
{
private string _foretaksnavn;
public string Foretaksnavn
{
get => _foretaksnavn;
set => SetAndNotify(ref _foretaksnavn, value);
}
// Etc, for all fields we want the user to fill in
public void Add()
{
// SQL, etc, etc
// Access the properties
sqlCmd.Parameters.AddWithValue("@Foretaksnavn", Foretaksnavn);
// Execute
// Tell LicenseHolderViewModel that it needs to reload
RequestClose(true);
}
public void Cancel()
{
// Tell LicenseHolderViewModel it doesn't need to reload
RequestClose(false);
}
} <Window x:Class="...AddView" ...>
<TextBox Text="{Binding Foretaksnavn}"/>
<!-- ... -->
</Window> Does that make sense? LicenseHolderViewModel has the BindableCollection of LicenseHolder. It opens AddViewModel. AddViewModel has properties for each of the fields we want the user to fill in, and those are bound to TextBoxes in the view. When it wants to insert a new record into the database, it reads from each of those properties, constructs the SQL query, executes it, and returns with 'true' to call LicenseHolderViewModel to reload. |
Beta Was this translation helpful? Give feedback.
Just stop and take a step back, please. You're making seemingly random changes, before I've even had a chance to catch up with the load of code you dumped on me previously.
Let's just simplify this a bit. You've got:
When the user clicks a button in LicenseHolderView, we show AddView. When they add a new license holder with AddView, we update the DataGrid.
Does that sound about right?
We've got a choice as to where we do the insertion into the database: in LicenseHolderView or in AddView. Let's do it in AddView, but either would work. We'…