Dispose ReportViewer object - wpf

How to Dispose ReportViewer object safely if application closed unexpectedly
Public Shared rv As New Microsoft.Reporting.WinForms.ReportViewer

I guess you are talking about issue mentioned here.
As mentioned in the link, you need to manually Dispose() the reportViewer instance on form closing event.
private void frmMyForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (rv != null && !rv.Disposing && !rv.IsDisposed)
{
rv.Dispose();
}
}
OR
Either calling reportViewer.LocalReport.ReleaseSandboxAppDomain() in form closing event:
private void frmMyForm_FormClosing(object sender, FormClosingEventArgs e)
{
rv.LocalReport.ReleaseSandboxAppDomain();
}

Related

Keep connection always open for datatable twoway bind?

I'm working on a WPF project which includes update/delete/insert operation on many tables. For simplicity, I use a datagrid for each table. The users can operate on these tables directly. Once done, click a button, the tables in database get updated. Twoway bind is perfect in this case. Below code seems working fine.
However, one thing I do not like is: the _DBConnection is always open. It is closed until the form exists. Usually, I always open connection whenever I need to, use it, close it immediately.
So, my question is: is below code the correct way to do the twoway bind?
thanks
public partial class MainWindow : Window
{
private OleDbConnection _DBConnection;
private OleDbDataAdapter _DataAdapterAdmin;
private DataSet _DataSetAdmin;
public MainWindow()
{
InitializeComponent();
}
private void InitAdminGrid()
{
string cmd = "SELECT * FROM Admin ORDER BY LastName";
_DataAdapterAdmin = new OleDbDataAdapter(cmd, _DBConnection);
_DataSetAdmin = new DataSet();
_DataAdapterAdmin.Fill(_DataSetAdmin);
dgAdministration.BeginInit();
dgAdministration.DataContext = _DataSetAdmin.Tables[0];
dgAdministration.Items.Refresh();
dgAdministration.EndInit();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
string connectionString = clsDataAccess.GetConnectionString();
_DBConnection = new OleDbConnection(connectionString);
_DBConnection.Open();
InitAdminGrid();
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
try
{
OleDbCommandBuilder cmd = new OleDbCommandBuilder(_DataAdapterAdmin);
_DataAdapterAdmin.Update(_DataSetAdmin);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Exception", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (_DBConnection != null)
{
_DBConnection.Close();
_DBConnection.Dispose();
}
}
}

Close current UserControl

I have a Window1.xaml main Window; and after some event, I display a UserControl EditFile.xaml.
The code behind is:
public static int whichSelected = -1;
private void button1_Click(object sender, RoutedEventArgs e)
{
//searchEditPanel.Children.Clear();
whichSelected = listViewFiles.SelectedIndex;
searchEditPanel.Children.Add(_EditFileControle); //this is Grid
}
And now, how can I close the opened/added UserControl from its content by clicking a Cancel button or something like that?
Window.GetWindow(this).Close();
You don't need to use a new variable, you can use it directly.
In your button click handler try :
Window parentWindow = (Window)this.Parent;
parentWindow.Close();
You could set the Visibility property of the control you want to "close" to Collapsed.
This way it will not be displayed anymore but will still be present in the visual tree if you need to reuse it later.
Have you tried this?
searchEditPanel.Children.Remove(_EditFileControle);
Another Suggestion:
Maybe this helps: http://sachabarber.net/?p=162
if it doesn't: Add a property to your UserControl:
public UserControl ParentControl {get;set;}
Now modify your code:
private void button1_Click(object sender, RoutedEventArgs e)
{
//searchEditPanel.Children.Clear();
whichSelected = listViewFiles.SelectedIndex;
_EditFileControle.ParentControl = this;
searchEditPanel.Children.Add(_EditFileControle); //this is Grid
}
Now you should be able to do this:
// Somewhere in your UserControl
if (this.ParentControl != null)
this.ParentControl.Children.Remove(this);
private void Button_Click(object sender, RoutedEventArgs e)
{
(this.Parent as searchEditPanel).Children.Remove(this);
}

Winforms StatusStrip - why are there periods where it is blank when I'm updating it?

BACKGROUND: I have a WindowForms v3.5 application with a StatusStrip set to be used as a TooStripStatusLabel. I'm issues quite a lot of updates to it during a task that is running, however there are noticable periods where it is BLANK. There are no points when I am writing a blank to the status strip label either.
QUESTION: Any ideas why I would be seeing period where the status strip label is blank, when I don't expect it to be?
How I update it:
private void UpdateStatusStrip(string text)
{
toolStripStatusLabel1.Text = text;
toolStripStatusLabel1.Invalidate();
this.Update();
}
PS. Calling Application.DoEvents() after the this.Update() does not seem to help. I actually am calling this via the backgroundworker control, so:
(a) I start up the background worker:
private void Sync_Button_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
DisableUpdateButtons();
}
(b) the background worker calls updates:
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
backgroundWorker1.ReportProgress(1, "Example string");
MainForm.MyC.SyncFiles(sender);
}
(c) The MyC business class uses it too, e.g.
public void SyncFiles(object sender)
{
BackgroundWorker bgw = (System.ComponentModel.BackgroundWorker) sender;
bgw.ReportProgress(1, "Starting sync...");
.
.
.
}
(d) This event picks it up:
private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
UpdateStatusStrip((string)e.UserState);
}
(e) And again the update status strip
private void UpdateStatusStrip(string text)
{
toolStripStatusLabel1.Text = text;
toolStripStatusLabel1.Invalidate();
this.Update();
}
Does this help?
The reason is possibly in the caller of this function. If you call it from another thread, use Control.BeginInvoke instead of direct call. If you call it from the main application thread during long processing, try Application.DoEvents after UpdateStatusStrip call.

Error with calling event inside another event

I am using silverlight, My code is set up for a usercontrol as follows:
myxaml.xaml (Just showing the toggle button [line 119])
<ToggleButton x:Name="btnToggleResizeMap" Checked="btnToggleResizeMap_Checked" Unchecked="btnToggleResizeMap_Unchecked" IsChecked="True"/>
codebehind.cs
public partial class MapRadar : UserControl
{
public delegate void OnMapExpandChange(object sender, EventArgs e);
public event OnMapExpandChange Expanded;
public event OnMapExpandChange NotExpanded;
private void btnToggleResizeMap_Checked(object sender, System.Windows.RoutedEventArgs e)
{
NotExpanded(this, null); //If i remove this line, the app runs fine
}
private void btnToggleResizeMap_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
Expanded(this, null); //If i remove this line, the app runs fine
}
}
Visual studio throws this error before the application is completely loaded:
AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 119 Position: 285]
at:
System.Windows.Application.LoadComponent(this, new System.Uri("/Xormis.Silverlight.ExSys;component/Views/Map/MapRadar.xaml", System.UriKind.Relative));
which is located inside a function named public void InitializeComponent()
I have no idea what is happening here, is there something against having event calls inside another event?
The problem is that you have null events. As soon as the checkbox is created, it immediately raises the Unchecked event, which calls your btnToggleResizeMap_Unchecked handler, which tries to call your Expanded event. Since Expanded is null, an exception is thrown, and it never finishes running the XAML.
Your code should look like this:
private void btnToggleResizeMap_Checked(object sender, System.Windows.RoutedEventArgs e)
{
if (NotExpanded != null)
NotExpanded(this, null);
}
private void btnToggleResizeMap_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
if (Expanded != null)
Expanded(this, null);
}
For a more thorough description of events, see C# Events and Thread Safety

C# EventHandler Beautiful Code (How To?)

I admit, it is kind of tiny, but I am looking for better ways to do the following code blocks. They should be self explaining...
private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var listBoxItem = sender as ListBoxItem;
if (listBoxItem != null)
{
var clickObject = listBoxItem.DataContext as ClickObject;
if (clickObject != null)
{
clickObject.SingleClick();
}
}
}
Another ugly one:
private void listBox_SelectionChangedA(object sender, SelectionChangedEventArgs e)
{
var lB = sender as ListBox;
if (lB != null)
StatusBoxA.Text = "Elements selected" + lB.SelectedItems.Count;
}
Yeah, I know, its not near-death-urgent. But I do NOT like the (if != null). Any magic ideas to shorten it even more :-)
Btw, I found some nice info about a similar topic: Loops on Null Items
Nice to read...
I love good, clean code but in most cases, clean & elegant doesn't mean short and smart. Code brevity is good for competitions. Changing an "if not null" statement to a foreach might seem way cooler but it's harder for everyone else working in the project to understand what you are trying to accomplish. Believe me, even you won't remember it a few months later :P. Your code is just fine as it is!
private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var listBoxItem = sender as ListBoxItem;
if (listBoxItem == null) return;
var clickObject = listBoxItem.DataContext as ClickObject;
if (clickObject == null) return;
clickObject.SingleClick();
}
One-liner:
private void listBox_SelectionChangedA(object sender, SelectionChangedEventArgs e)
{
As<ListBox>(sender, (lB) => StatusBoxA.Text = "Elements selected" + lB.SelectedItems.Count);
}
or, nested:
private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
As<ListBoxItem>(sender, (listBoxItem) => {
As<ClickObject>(listBoxItem.DataContext,
(clickObject) => clickObject.SingleClick());
};
}
using this static generic method (T is destination type, input is object to cast, code is a delegate (or lambda expression) to execute on success:
static void As<T>(object input, Action<T> code) where T : class
{
T foo = input as T;
if (foo != null)
code(foo);
}
Since you're using known events from the .NET framework (as opposed to a third party) and from the code it looks like you're only using those methods for specific classes (i.e. ListBoxItems and ListBoxes), there are a few things you know to be true:
sender will never be null
sender will always be a ListBoxItem, or ListBox, respectively
So why use the as operator? Just cast!
Then the first snippet becomes
private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var listBoxItem = (ListBoxItem)sender;
var clickObject = (ClickObject)listBoxItem.DataContext;
clickObject.SingleClick();
}
Note this isn't true in the general case (you wouldn't do this if you were handling all PreviewMouseDown events in that one handler for all Control types), but for event handling code like this, especially in UI code, you can be as certain as you can be of anything, that sender will not be null and sender will be of the type you expect.
Maybe I am just being pedantic but why do you need to cast the sender if you are using the event within its host containers code.
Regardless of who made the change to a list, couldn't you just give your listbox a name and use that.
<ListBox x:Name="listbox1" />
private void listBox_SelectionChangedA(object sender, SelectionChangedEventArgs e)
{
StatusBoxA.Text = "Elements selected" + listbox1.SelectedItems.Count;
}
Or you could even achieve some of this using binding with no code behind.
This is supposed to be the same as the first one, reformatted a little:
private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
ClickObject clickObject;
if (
((sender as ListBoxItem) != null) &&
((clickObject = ((ListBoxItem)sender).DataContext as ClickObject) != null)
)
{
clickObject.SingleClick();
}
}
You can add extensions methods to Form elements, which can then trigger the events:
public static void OnSelectionChanged(this ListBox b, Action<ListBox> a)
{
b.SelectedIndexChanged += (s,e) =>
{
if (s is ListBox)
a(s as ListBox);
};
}
Using the same idea as Utaal's solution, but as an extension method...
public static void As<TSource>(this object item, Action<TSource> action) where TSource : class
{
var cast = item as TSource;
if (cast != null)
action(cast);
}
private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
sender.As<ListBoxItem>(listBoxItem =>
listBoxItem.DataContext.As<ClickObject>(clickObject =>
clickObject.SingleClick()));
}

Resources