Obtain values from current row when databinding - c#

I'm using DevExpress XtraReports in a WinForms application, but could equally apply to other reporting tools.
I'd like to perform some logic per-row in the report as it is "rendered", on a row-by-row basis. Specifically I'd like to hide a barcode if the data for the barcode isn't available.
Currently I'm doing the following:
private void xrBarCode2_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
var barcode = (XRBarCode)sender;
if (barcode.Text.Trim() == "")
{
barcode.Visible = false;
lblWarning.Visible = true;
}
else
{
barcode.Visible = true;
lblWarning.Visible = false;
}
}
But that just plain smells bad. I'd like to access the current data row in this method and work on the "real" properties of the object, but can't. What is the typical pattern for this in other report generators? Am I even using the correct event? I tried Detail_BeforePrint, but that had no additional information.

Use Detail_BeforePrint in conjunction with GetCurrentColumnValue() like so:
private void Detail_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e) {
if (string.IsNullOrEmpty(GetCurrentColumnValue("BarcodeColumnName"))) {
barcode.Visible = false;
lblWarning.Visible = true;
} else {
barcode.Visible = true;
lblWarning.Visible = false;
}
}

Related

How to disable xamdatagrid cell editing in wpf

I used xamdatagrid cellupdated event,inside that event i have to disable the specific cell in editing and want to enable it after getting the response of an API call,the problem is when i enable the cell after disabling it,the cursor wont set in the correct position.
private async void RenewDataGrid_OnCellUpdated(object sender, CellUpdatedEventArgs e)
{
row.Cells[4].IsEnabled = false;
await datacontext.CalculateFdtotalAmount();
row.Cells[4].IsEnabled = true;
}
I have had similar types of issues with XamDataGrid within a function call. I solved it by processing the statements like the old windows PeekMessage. To do that, try something like:
private async void RenewDataGrid_OnCellUpdated(object sender, CellUpdatedEventArgs e)
{
row.Cells[4].IsEnabled = false;
DoEvents();
await datacontext.CalculateFdtotalAmount();
DoEvents();
row.Cells[4].IsEnabled = true;
}
public object ExitFrame(object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}
public void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}

Calling an SQL stored procedure that's defined in a method using button click on form c#

Having a lot of trouble with this. I'm working on a large project, so there's only a few classes I'm interested in and working on. Basically, these are forms - one is a main editor where a user edits details and the other is used to assign a pin number. In the main editor form, if the user has a pin, they can choose to edit this pin. Here's where my problem lies - if I edit the pin, what I'm doing in the code is deleting the old pin and adding the new one. However, the database doesn't update until AFTER the editor form is closed. Therefore, I'd like to call the method that does change the database on the OKButton click, if I could. The problem I'm facing is I don't know how.
Here is the DB code, we'll say the class is called DetailsConn:
public string editPin(int driverID)
{
if (SchemaChecker.PINAvailable())
{
string sql = "EditPIN";
using (SqlCommand cmd = new SqlCommand(sql, base.connection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Remove("#nDriverID");
cmd.Parameters.AddWithValue("#nDriverID", driverID);
cmd.Parameters.Remove("#nPIN");
SqlParameter pinParameter = cmd.Parameters.Add("#nPIN", SqlDbType.Char);
pinParameter.Direction = ParameterDirection.Output;
pinParameter.Size = 32;
cmd.ExecuteNonQuery();
return pinParameter.Value.ToString();
}
}
return "";
}
Here's the code for my edit:
private void editToolStripMenuItem_Click(object sender, EventArgs e)
{
if (this.listViewDriverTags.SelectedItems.Count > 0)
{
ListViewItem lvi = this.listViewDriverTags.SelectedItems[0];
DriverTag driverTag = lvi.Tag as DriverTag;
else if (blahTag.blahType == 2)
{
buttonAssignPIN_Click(sender, e);
}
//message stuff and dialog boxes with localization info
if (dr == DialogResult.Yes)
{
this.listViewDriverTags.Items.Remove(lvi);
if (Tag.id != -1)
{
TagsToBeDeleted.Add(driverTag);
}
}
if (dr == DialogResult.No)
{
this.listViewTags.Items.Clear();
this.listViewTags.Items.Add(lvi);
}
}
}
Here's my buttonAssignPIN stuff:
private void buttonAssignPIN_Click(object sender, EventArgs e)
{
using (AssignPINForm form = new AssignPINForm())
{
if (form.ShowDialog(this) == DialogResult.OK)
{
DriverTag PIN = DriverTag.GetNewPIN(form.DriverTag);
ListViewItem lvi = this.listViewTags.Items.Add(PIN.driverTag);
lvi.SubItems.Add(this.TagTypes[PIN.TagType]);
lvi.Tag = PIN;
}
}
}
And finally, here's my AssignPINForm code:
public partial class AssignPINForm : Form
{
public AssignPINForm()
{
InitializeComponent();
this.buttonOK.Click += new EventHandler(buttonOK_Click);
this.buttonCancel.Click += new EventHandler(buttonCancel_Click);
this.buttonOK.Enabled = false;
this.textBoxPin.TextChanged += delegate(object sender, EventArgs e)
{
String pattern = #"^[0-9]{4,20}$";
Regex regex = new Regex(pattern);
buttonOK.Enabled = regex.IsMatch(textBoxPin.Text);
};
LoadStrings();
}
public void LoadStrings()
{
//stome stuff
}
public string DriverTag
{
get { return this.textBoxPin.Text; }
set { this.textBoxPin.Text = value; }
}
private void buttonOK_Click(object sender, EventArgs e)
{
}
private void buttonCancel_Click(object sender, EventArgs e)
{
this.Close();
}
private void AssignPINForm_Load(object sender, EventArgs e)
{
}
}
I know it's kind of all over the place but I've provided everything I think is relevant. The middle two snippets are in the same class too, and the DB stuff is the same solution but a different project. I'd be grateful if someone can decipher what I'm after and help me out, it's the only thing I have left to do on this particular bit!
Thanks!
Not sure I fully got what you're after and I agree with some of the comments that this isn't the best of practice but I guess what you're after is to update the buttonOK_Click method to something like this:
private void buttonOK_Click(object sender, EventArgs e)
{
using(DetailsConn connection = new DetailsConn())
{
int driver = -1;
if(int.TryParse(this.DriverTag, out driver)) {
connection.editPin(driver);
}
}
}
Also, you may want to remove any other possible references to the editPin() function.
I actually figured out that even if I got that working correctly, it wasn't going to solve my problem. I've had to call a new procedure and declare that in the database schema - basically it was a lot more complicated than what I was giving it credit for. Thanks for the responses nonetheless.

Setting IsEnabled on a ribbon textbox to true doing nothing

I am working on a program to manage a minecraft server with a local UI as well as a remote interface. I have a button on a ribbon bar that will enable or disable the remote interface and a textbox for inputting the port. Currently, I disable the textbox when the networking is enabled, but, disabling does not re-enable the textbox after I set it to true again (and setting a breakpoint reveals it to still be false).
private void NetToggleChecked(object sender, RoutedEventArgs e) {
portTextBox.IsEnabled = false;
if (ButtonPressedByUser) {
var result = MessageBox.Show("Are you sure you want to enable networking with the current settings?" +
" If not properly configured, it may be possible for an attacker to enter your server.",
"Simple Bukkit Wrapper", MessageBoxButton.YesNo, MessageBoxImage.Warning,
MessageBoxResult.No);
if (result == MessageBoxResult.No) {
ButtonPressedByUser = false;
NetworkToggle.IsChecked = false;
ButtonPressedByUser = true;
return;
}
}
Config.NetConf["enabled"] = "true";
int port;
if (!int.TryParse(Config.NetConf["port"], out port)) {
MessageBox.Show("Port could not be parsed (is it a number?)");
ButtonPressedByUser = false;
NetworkToggle.IsChecked = false;
ButtonPressedByUser = true;
return;
}
Net.Listener.StartListening(port);
}
private void NetworkToggleUnchecked(object sender, RoutedEventArgs e) {
portTextBox.IsEnabled = true;
if (ButtonPressedByUser) {
var result =
MessageBox.Show("Are you sure you wish to disable all networking to your server? It will " +
"be impossible to connect to it remotely and any existing connections will be closed.",
"", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (result == MessageBoxResult.No) {
ButtonPressedByUser = false;
NetworkToggle.IsChecked = true;
ButtonPressedByUser = true;
return;
}
}
Config.NetConf["enabled"] = "false";
Net.Listener.StopListening();
}
Thank you for any help resolving why the textbox will not enable again.
Old Question but i kept coming across it while searching for an answer so figured i'd post an answer anyways. There is a bug in the ribbonTextbox control that results in isenabled always being false if there is no command associated. There are 2 ways round this from what i have found:
1: Create a new control based on the ribbontextbox and override the isenabledcore property to always return true. As shown here Cannot set RibbonTextBox isEnable to False
2: Create a dummy command and associate it with the control
public static readonly ICommand DummyCommand = new RoutedCommand("Dummy", typeof(Control));
public static void Dummy(Object sender, ExecutedRoutedEventArgs e)
{
// Do nothing its a dummy command
}
public static void CanDummy(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
as described in a comment in this link http://blogs.msdn.com/b/wpf/archive/2010/10/21/wpf-ribbon-october-2010-update-details.aspx .
AS i said probably no help to the original poster but i kept coming across it while looking for an answer so it may save someone else a few minutes of googling time.

How To Improve Filter Speed in ObservableCollection

I am using an ObservableCollection bound to a WPF DataGrid, the collection contains instances of a custom class (About 500) and the custom class is relativly basic (2 Strings, an IP and a custom enum)
I am using the following code to filter the grid (using all columns) as text is typed into a textbox.
private void searchBox_TextChanged(object sender, TextChangedEventArgs e)
{
CollectionViewSource SearchView = new CollectionViewSource();
SearchView.Filter += Search_Filter;
SearchView.Source = HostList;
dataGridMain.ItemsSource = SearchView.View;
}
void Search_Filter(object sender, FilterEventArgs e)
{
if (e.Item != null)
{
Host host = e.Item as Host;
try
{
bool foundInHost = false;
bool foundInIP = false;
bool foundInUser = false;
foundInHost = host.Hostname.ToLower().Contains(searchBox.Text.ToLower());
foundInIP = host.IP.ToString().Contains(searchBox.Text.ToLower());
foundInUser = host.Username.ToString().Contains(searchBox.Text.ToLower());
if (foundInHost || foundInIP || foundInUser)
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
catch (Exception ex)
{
}
}
}
It works but even on my shiny new i7 Laptop takes way too long.
Can anyone suggest a quicker method of filtering an observable collection?
Well all the ToLower and contains stuff isn't helping, but the most immediate fix would be
bool found = host.Hostname.ToLower().Contains(searchBox.Text.ToLower());
if (!found)
{
found = host.IP.ToString().Contains(searchBox.Text.ToLower());
if (!found)
{
found = host.Username.ToString().Contains(searchBox.Text.ToLower());
}
}
Don't need the other tests if one of them is already true.
searchBox.CharacterCasing to Lower would help as well.
And get rid of that exception swallow as well (the try catch). That's a really bad habit.
At the very least add an errorlog to the app, log the exception and then swallow.

I want to programmatically generate a click on a DataGridView Row in C#

I have a DataGridView in a form and I want to programmatically click its first row. I have found code to select its rows or columns from code.
For eg.
datagridview.Columns[0].Selected = true;
datagridview.Rows[0].Selected = true;
However this code is not raising the click event on the datagridview. If any one has coded how to click a datagridview from code, please extend your kind help.
Simply call the event handler method e.g.:
datagridviewRowClickedEventHandler(new object(), new eventargs());
If you use the sender or e parameters in the event handler then you will need to work out how to pass in the correct values.
Insert the follwing code into your project where appropriate (Usually on the form which has the datagridview).
Make sure to change the name of the DataGridView from dataGridView1 to the appropriate one on your form.
private void Form1_Load(object sender, EventArgs e)
{
//call the cell click event with the first cell as the parameters.
dataGridView1_CellClick(dataGridView1, new DataGridViewCellEventArgs(0, 0));
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
//put your code for handling cell click here
}
It looks like you have the first half, setting the propers rows Selected value to true. Now you can programatically call the row click handler and it should proceed as if you had clicked it within the GUI.
datagridview.Columns[0].Selected = true;
datagridview.Rows[0].Selected = true;
It makes look the row like selected but it won't change dataGridView.CurrentRow. So it could be an issue.
dataGridView.CurrentCell = dataGridView[<column>, <row>];
will change CurrentRow value too.
Hope it will help.
I assume you want to apply DataSource and select the first row? Right?
The best way to do it like this
private async void DgvAreas_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
{
}
And here is the code to simulate click on row.
DgvAreas_RowStateChanged(dgvAreas, new DataGridViewRowStateChangedEventArgs(dgvAreas.Rows[0], DataGridViewElementStates.Selected));
In my case I have 3 DataGridViews so I populate the first one easly.
The second one I populate when user click the first DataGridView and in this case I use DgvStaff_RowStateChanged event.
And in this event DgvStaff_RowStateChanged I have the code to get data async and populate the third DataGridView and after I apply data source for the second DataGridView I need to get data for the first row of this view and display it in the third DataGridView. It is cascade logic.
private async void DgvStaff_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
{
try
{
// For any other operation except, StateChanged, do nothing
if (e.StateChanged != DataGridViewElementStates.Selected) return;
if (sender is MetroFramework.Controls.MetroGrid)
{
if ((sender as MetroFramework.Controls.MetroGrid).SelectedRows.Count > 0)
{
dgvGeoData.DataSource = null;
dgvAreas.DataSource = null;
metroProgressSpinnerMain.Visible = true;
panelFilter.Enabled = false;
dgvAreas.RowStateChanged -= DgvAreas_RowStateChanged;
var selectedRow = (sender as MetroFramework.Controls.MetroGrid).SelectedRows[0];
var machineModelShortView = (MachineModelShortView)selectedRow.DataBoundItem;
var startTime = Convert.ToDateTime(dateTimePickerStart.Value.ToShortDateString());
var endTime = Convert.ToDateTime(metroDateTimeEnd.Value.ToShortDateString());
var areas = await UpdateAreaItems(machineModelShortView.MachineID, startTime, endTime);
if (areas.Any())
{
BeginInvoke((Action)(() =>
{
dgvAreas.DataSource = areas.OrderBy(x => x.AreaID).ThenBy(x => x.TimeStart).ToList();
dgvAreas.RowStateChanged += DgvAreas_RowStateChanged;
// !!! This is how you simulate click to the FIRST ROW dgvAreas.Rows[0]
DgvAreas_RowStateChanged(dgvAreas,
new DataGridViewRowStateChangedEventArgs(dgvAreas.Rows[0], DataGridViewElementStates.Selected));
metroProgressSpinnerMain.Visible = false;
panelFilter.Enabled = true;
}));
}
else
{
BeginInvoke((Action)(() =>
{
metroProgressSpinnerMain.Visible = false;
panelFilter.Enabled = true;
}));
}
}
}
}
catch (Exception ex)
{
logger.Error(ex);
}
}
And here
private async void DgvAreas_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
{
try
{
// For any other operation except, StateChanged, do nothing
if (e.StateChanged != DataGridViewElementStates.Selected) return;
//Get GeoData
if (sender is MetroFramework.Controls.MetroGrid)
{
if ((sender as MetroFramework.Controls.MetroGrid).SelectedRows.Count > 0)
{
dgvGeoData.DataSource = null;
metroProgressSpinnerMain.Visible = true;
panelFilter.Enabled = false;
var selectedRow = (sender as MetroFramework.Controls.MetroGrid).SelectedRows[0];
var areaItem = (AreaItem)selectedRow.DataBoundItem;
var geoData = await UpdateWDataPositionItems(areaItem.MachineID, areaItem.TimeStart, areaItem.TimeEnd.Value);
if (geoData.Any())
{
BeginInvoke((Action)(() =>
{
dgvGeoData.DataSource = geoData.OrderBy(x => x.AtTime).ToList();
metroProgressSpinnerMain.Visible = false;
panelFilter.Enabled = true;
}));
}
else
{
BeginInvoke((Action)(() =>
{
metroProgressSpinnerMain.Visible = false;
panelFilter.Enabled = true;
}));
}
}
}
}
catch (Exception ex)
{
logger.Error(ex);
}
}

Categories