WPF Datagrid get data on CheckboxChecked-Event - wpf

I've got a datagrid with a checkbox, name and email.
On CheckboxChecked I want to copy the email into another list or string.
How do I get the specific value from the checked row?
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
object row = lbxCC1.SelectedItem;
int columnIndex = lbxCC1.Columns.Single(c => c.Header.Equals("eMail")).DisplayIndex;
String eMail = (lbxCC1.SelectedCells[columnIndex].Column.GetCellContent(row) as TextBlock).Text;
MessageBox.Show(eMail);
}
Edit (09.09.2016):
Maybe I should show you a bit more code.
public class Person
{
public string Nachname { get; set; }
public string Vorname { get; set; }
public string eMail { get; set; }
public string Abteilung { get; set; }
}
public static class PersonService
{
public static List<Person> ReadFile(string filepath)
{
var lines = File.ReadAllLines(filepath);
var data = from l in lines.Skip(1)
let split = l.Split(';')
select new Person
{
Nachname = split[1],
Vorname = split[2],
eMail = split[31],
Abteilung = split[4],
};
return data.ToList();
}
}
I call it with:
lbxCC1.DataContext = PersonService.ReadFile(#"C:\Test.csv");
As I'm building the columns from code behind, I guess I have to bind them aswell am I right?
Sorry for this, but I'm new to datagrids :-)

I think this might help you:
Dim row As Data.DataRowView = DirectCast([yourDataGrid].SelectedItems(rowIndex), Data.DataRowView)
Then in your CheckBox_Checked Event:
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
MessageBox.Show(row("email"); 'Assuming the column name is email
}
This is IF your values are data-bound to the DataGrid.

Related

Winforms, EF Core, dropdown combobox bound to BindingSource. Is there a descent way of persisting newly added items? BindingList?

I am trying to build a Patient's edit form that will get Patient data from a database using EF Core and the DbContext derived AppDbContext.
On the same form there will be a dropdown combobox that will be displaying all the available insurances (fetched from the database).
What I want to achieve is the ability, the user to be able to select an existing insurance (which is obvious and easily achieved) or to add a new one by typing it into the combobox and this new entry should be selected as the patient's insurance from now on until the SaveChanges takes place and when the same patient is reopened for editing.
I use two BindingSources one for the patient itself (bsPatient) and one for the insurances list (bsInsurances).
I have the following two models (1:many relationship)
public class Insurance
{
public int Id { get; set; }
public string Name { get; set; } = String.Empty;
public virtual ObservableCollectionListSource<Person> Persons { get; } = new();
}
public class Person
{
public int Id { get; set; }
public string LastName { get; set; } = String.Empty;
public string FirstName { get; set; } = String.Empty;
public DateTime DOB { get; set; }
public int InsuranceId { get; set; }
public Insurance Insurance { get; set; } = null;
}
And this is the DbContext:
public class AppDbContext : DbContext
{
private const string DatabaseFileName = "MyPatientsDB.sqlite3";
public DbSet<Person> Persons { get; set; }
public DbSet<Insurance> Insurances { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder
.UseSqlite(#$"Data Source={DatabaseFileName}");
On the form there will be
public partial class PatientForm : Form
{
private AppDbContext _db = new();
private int _patientId = 0;
ObservableCollection<Insurance> _insurancesList = new();
public PatientForm(int patientId)
{
InitializeComponent();
_patientId = patientId;
}
protected async override void OnLoad(EventArgs e)
{
base.OnLoad(e);
await _db.Insurances.LoadAsync();
_insurancesList = new ObservableCollection<Insurance>(_db.Insurances.Local);
bsInsurances.DataSource = _insurancesList;
bsPatient.DataSource = await _db.Persons.FirstOrDefaultAsync(p => p.Id == _patientId);
}
protected async override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
bsInsurances.EndEdit();
if (cbInsurances.FindStringExact(cbInsurances.Text) == -1)
{
var newInsurance = new Insurance { Id = 0, Name = cbInsurances.Text };
_db.Insurances.Local.Add(newInsurance);
}
bsPatient.EndEdit();
await _db.SaveChangesAsync();
_db?.Dispose();
}
}
So far, I am able to save correctly the Insurance selection of the combobox when an already existing item is selected. The problem arises when the user inserts a new insurance entry into the combo textbox. This new entry can not be saved to the db and be displayed the next time the same patient is opened for editing.
I would be grateful if someone could point me towards which direction to follow to achieve this. I mean, while editing a patient's data how to be able to insert a new entry into the insurances combo and this new entry to be persisted into the db and be displayed and selected the next time the patient is opened for editing.
I think I've found a solution. I don't know if it is the best one but it seems to be working at least into my project. I am just referring it in case someone else has the same query.
Please if anyone has a better solution I would be grateful for his/her help.
protected async override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
bsInsurances.EndEdit();
if (cbInsurances.FindStringExact(cbInsurances.Text) == -1)
{
if (bsPatient != null && bsPatient.DataSource != null)
{
(bsPatient.DataSource as Person).Insurance = new Insurance() { Name = cbInsurances.Text as string };
}
}
bsPatient.EndEdit();
await _db.SaveChangesAsync();
_db?.Dispose();
}

Bindingsource on combobox

I create the small winform to do test bing
Existing class as below
public class Book
{
public int Id { get; set; }
public string BookName { get; set; }
public int? CatalogID { get; set; }
}
public class BookCatalog
{
public int Id { get; set; }
public string CataLogName { get; set; }
}
and I create the form with two control, Textbox and Combobox
which initial as below
private Book BookRecord;
private List<BookCatalog> bookCatalogs;
private BindingSource BindingSource = new BindingSource();
public frmBook()
{
InitializeComponent();
// I have initial one bookrecord and multi bookCatalogs here
cbBookCatagories.DisplayMember = "CataLogName";
cbBookCatagories.ValueMember = "Id";
cbBookCatagories.DataSource = bookCatalogs;
BindingSource.DataSource = BookRecord;
txtBoxBookName.DataBindings.Add("Text", BindingSource, "BookName");
cbBookCatagories.DataBindings.Add("SelectedValue", BindingSource, "CatalogID");
}
The first run is fine, but when I want to clear BookRecord as below code
BookRecord.Id = 0;
BookRecord.BookName = null;
BookRecord.AuthorName = null;
BookRecord.CatalogID = null;
BindingSource.ResetBindings(false);
My combobox cannot change value and always point to zeroindex
can anyone guide me how to handle BindingSource() on comboxbox ?
Thank you

VS 2017 WPF save application data

i want to ask how to permanently save user input data read in through different TextBoxes and only temporary saved in a DataGrid (Data get lost after closing the application).
I do not want to use SQL for this application. I just want to store the user input data constantly even if closing VS2017.
Is there a commando to make it possible?
Code As Requested:
namespace New_Adress_Book
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
dg.ItemsSource = personen;
}
List<Person> personen = new List<Person>();
private void Button_Speichern(object sender, RoutedEventArgs e)
{
personen.Add(new Person(Vorname.Text, Nachname.Text, Strasse.Text, Hausnummer.Text, Ort.Text, TelNr.Text));
dg.Items.Refresh();
}
}
class Person
{
public Person (string vn, string nn, string str, string hnr, string ort, string telnr)
{
this.Vorname = vn;
this.Nachname = nn;
this.Strasse = str;
this.Hausnummer = hnr;
this.Ort = ort;
this.Telefonnummer = telnr;
}
// Something seems to be missing here...
public string Vorname
{
get;
set;
}
public string Nachname
{
get;
set;
} ...
}
}
Sorry for any grammatical mistakes you will find and sorry for any offense against the Forum rules. I am really new to this!

WPF: set log level and refresh collection after changing

So I have form that show my Application Log.
This is my Log model:
public class LogEntry : IComparable<LogEntry>
{
public string DateTime { get; set; }
public int Index { get; set; }
public string Source { get; set; }
public Level Level { get; set; }
public string Message { get; set; }
public int CompareTo(LogEntry other)
{
return DateTime.CompareTo(other.DateTime);
}
}
public enum Level
{
All = 0,
Debug,
Info,
Warn,
Error,
Fatal,
Off
}
Log Helper
This is my LogHelper class that add the current LogEvent according the level that the user selected:
public static class LogHelper
{
public static ObservableCollection<LogEntry> LogEntries { get; set; }
public static bool AddLogToList { get; set; }
private static int _level;
private static int _index;
private static string _formatPattern = "yyyy-MM-dd HH:mm:ss,fff";
public static void SetLevel(Level level)
{
_level = (int)level;
}
public static void AddLog(Level level, string message, string className, string methodName)
{
if (LogEntries == null)
LogEntries = new ObservableCollection<LogEntry>();
if (AddLogToList)
{
int levelValue = (int)level;
if (levelValue >= _level)
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
if (LogEntries.Count == 1000)
LogEntries.RemoveAt(LogEntries.Count - 1);
LogEntry logEntry = new LogEntry()
{
DateTime = DateTime.Now.ToString(_formatPattern),
Index = _index++,
Level = level,
Source = className + "\\" + methodName,
Message = message.Trim()
};
LogEntries.Insert(0, logEntry);
}));
}
}
}
}
So I am add LogEvent into my list that contains up ti 1000 entries.
Now I want to be able to filter and show my only the relevant LogEvent Level.
So I added ComboBox with all my LogEvent levels and subscribe to its SelectionChanged event:
private void cbLogLevel_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
int index = cbLogLevel.SelectedIndex;
LogHelper.SetLevel((Level)index);
lvLogger.ItemsSource = LogHelper.LogEntries.Where(m => m.Level == (Level)index).ToList();
}
So after this SelectionChanged event I can see the relevant LogEvent level but my only issue is the new LogEvent not shows.
Maybe I need kind of refresh to my collection or something else ?
You are creating a new List<LogEntry> and setting the ItemsSource property to this one in your event handler. This means that lvLogger will no longer be connected to the ObservableCollection.
Instead of resetting the ItemsSource, you could filter the view:
private void cbLogLevel_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
int index = cbLogLevel.SelectedIndex;
Level level = (Level)index;
LogHelper.SetLevel(level);
var collectionView = CollectionViewSource.GetDefaultView(lvLogger.ItemsSource);
collectionView.Filter = x =>
{
LogEntry logEntry = x as LogEntry;
return logEntry != null && logEntry.Level == level;
};
}

How to show list data into datagridview?

I'm trying to bind a list of data to a data grid, but can't do it. I'm giving my code here.
I have made a class like this:
public class Book
{
int bookID;
string bookName;
string athourName;
public Book(int BookID, string BookName, string AuthorName)
{
bookID = BookID;
bookName = BookName;
athourName = AuthorName;
}
}
Under form load event, I wrote the following code:
private void Form1_Load(object sender, EventArgs e)
{
Book Book1 = new Book(001, "Java", "Harbart");
Book Book2 = new Book(002, "C", "Balaguru");
string[] BookArray = new string[10];
BookArray[0] = Book1.ToString();
BookArray[1] = Book2.ToString();
List<Book> Obj = new List<Book>();
Obj.Add(Book1);
Obj.Add(Book2);
dataGridView1.DataSource = Obj;
}
This doesn't give any error, but also not showing any data in the data grid. I have a feeling I'm missing something in between. A clarification on how to bind data to data grid would be very helpful.
The DataGridView requires public properties to autogenerate its columns. It will not work with fields, either public or private.
Change your class to this:
public class Book
{
public int bookID { get; set; }
public string bookName { get; set; }
public string athourName { get; set; }
public Book(int BookID, string BookName, string AuthorName)
{
bookID = BookID;
bookName = BookName;
athourName = AuthorName;
}
}
That uses auto-properties but you can of course use the longhand syntax as well.

Resources