Laden...

Forenbeiträge von Jessimaus Ingesamt 6 Beiträge

20.09.2017 - 15:47 Uhr

Hallo Jamikus,

vielen Dank für Deine Hinweise.

Die SQL-Verbindung ist Bestandteil von MdbCon und die ist in der Regel geschlossen.
Die Prüfung auf NULL im Konstruktor könnte man in der Tat weglassen, weil, wenn dieses Teil NULL ist, dann stirbt die ganze Anwendung ab.
Ich hatte mal die 30-Tage Testversion vom Resharper drauf und der hat rumgemeckert von wegen 'possible System.NullReferenzExceprion'.

Geschlossen wird die SQL-Verbindung automatisch zusammen mit dem Reader, wegen CommandBehavior.CloseConnection.

Wegen der using mache ich mir Gedanken, was passiert, wenn innerhalb dieser Blöcke irgendwas schiefgeht. Dann fliegt mir bzw. dem
Benutzer eine unbehandelte Ausnahme um die Ohren. Vielleicht sollte man innerhalb der using-Blöcke ein try/catch einbauen? Oder außen herum?

@T-Virus
Ich brauche eine Liste/Collection vom Typ Artikelstamm, warum soll ich also nicht von Collection ableiten?

Mit

var Artikelliste = new LstArtikelstamm(MdbCon);

baue ich mir die Liste, die ich ans DataGrid oder die Combobox binde. Einfacher geht's doch gar nicht, oder? Leite ich nicht von Collection ab,
sondern erstelle die Liste innerhalb einer einfachen Klasse, habe ich doch auch nichts anderes als die Liste aller Artikel.

Gruß Jessimaus

20.09.2017 - 10:22 Uhr

Hallo Leute,

habe gerade gesehen, dass man hier eigene Programme oder Teile davon zur 'Begutachtung' bzw. Diskussion vorstellen kann.
Ich benötige in unserem Projekt etliche Listen, so dass ich die immer nach dem gleichen Schema erstellen möchte.
Ich habe mich weitgehend an der Vorgehensweise im Doberenz orientiert.
Die unten beispielhaft angeführte Klasse LstArtikel würde ich dann als Basisklasse für DtoArtikel verwenden wollen,
die um die Bearbeitungsfunktionen Insert, Update und Delete erweitert ist.

Wie man schnell sieht, ist es nichts kompliziertes aber vielleicht gibt es ja den einen oder anderen hilfreichen Hinweis oder gar grundsätzliche Einwände.
Beispielsweise bin ich nicht sicher, ob das using nicht besser durch einen try/catch-Block ersetzt werden sollte.

Ich freue mich auf eure Kommentare
Liebe Grüße Jessimaus


#region using-Anweisungen
	using System;
	using System.Collections.ObjectModel;
	using System.Data;
	using System.Data.SqlClient;
	using System.Globalization;
	using Model.POCO;
	using Model.POCO.Database;
#endregion
namespace ViewModel.Lists{
	public class LstArtikelstamm : Collection<Artikelstamm>{

		private readonly	SqlConnection _SqlCon;
		private readonly	int _MandantenID;
		private const string COMMANDTEXT =
			@"SELECT * FROM [dbo].[ilfSelectArtikelliste](@MandantenID)";

		public LstArtikelstamm(MdbConnection MdbCon){
			if(MdbCon == null) return;

			_SqlCon		= MdbCon.SqlCon;
			_MandantenID	= MdbCon.MandantenID;
			fill_Liste();
		}	// End Konstruktor

		private void fill_Liste(){
			using(var _SqlReaderCommand = POCOModelBase.get_SqlCommand()){
				if(_SqlReaderCommand == null) return;

				_SqlReaderCommand.Connection	= _SqlCon;
				var _DrPrmMandantenID = new SqlParameter("@MandantenID", SqlDbType.Int){
					Direction = ParameterDirection.Input
				};
				_SqlReaderCommand.Parameters.Add(_DrPrmMandantenID);
				_SqlReaderCommand.CommandText = COMMANDTEXT;
				if(_SqlCon.State != ConnectionState.Open){
					_SqlCon.Open();
				}
				Clear();
				_SqlReaderCommand.Parameters[0].Value = _MandantenID;
				using(var _Reader = _SqlReaderCommand.ExecuteReader(CommandBehavior.CloseConnection)){
					if(!_Reader.HasRows) return;

					while(_Reader.Read()){
						var Listenartikel = new Artikelstamm{
							MandantenID	= _MandantenID,
							ArtikelID	= Convert.ToString(_Reader["ArtikelID"], CultureInfo.CurrentCulture),
							Artikelname	= Convert.ToString(_Reader["Artikelname"], CultureInfo.CurrentCulture),
							SteuersatzID	= Convert.ToInt32(_Reader["SteuersatzID"], CultureInfo.CurrentCulture),
							KategorieID 	= Convert.ToInt32(_Reader["KategorieID"], CultureInfo.CurrentCulture),
							GruppenID	= Convert.ToInt32(_Reader["GruppenID"], CultureInfo.CurrentCulture),
							Bearbeiter	= Convert.ToString(_Reader["Bearbeiter"], CultureInfo.CurrentCulture),
							LetzteAenderung	= Convert.ToDateTime(_Reader["LetzteAenderung"], CultureInfo.CurrentCulture),
							Zeilenversion	= _Reader.GetFieldValue<byte[]>(_Reader.GetOrdinal("Zeilenversion")),
							Anzahl		= Convert.ToInt32(_Reader["Anzahl"], CultureInfo.CurrentCulture)
						};
						Add(Listenartikel);
					}	// End While
				}	// End using - Reader
			}	// End Using - SQLCommand
		}	// End fill_Liste
	}	// End class
}	// End namespace

20.09.2017 - 09:06 Uhr

Hallo Leute,

ich habe ein Problem bei der Verwendung des BackgroundWorkers.
Die Ausgangssituation ist folgende: Ich erstelle eine Instanz des ViewModels und übergebe dieses dann an das aufzurufende Formular.
Da für das Formular eine Liste mit mehreren 100tausend Datensätzen benötigt wird, die Datenleitung mitunter aber recht schlecht ist,
habe ich diese Liste mittels BackgroundWorker im OnLoad-Ereignis des Formulars nachgeladen. Nachdem ich diese Funktionalität ins
ViewModel verschoben habe, erhalte ich regelmäßig wenig aufschlussreiche Fehlermeldungen.> Fehlermeldung:

"Für den aktuellen Befehl ist ein schwerwiegender Fehler aufgetreten. Löschen Sie eventuelle Ergebnisse."

Im Konstruktor des ViewModels steht u.a. folgendes:

// ...
Worker = new BackgroundWorker{
	WorkerReportsProgress = true,
	WorkerSupportsCancellation = true
};
Worker.DoWork += worker_DoWork;
Worker.RunWorkerCompleted += worker_RunWorkerCompleted;

refresh_Geraeteliste();
} // End Konstruktor

DoWork:


private void worker_DoWork(object sender, DoWorkEventArgs e){
	IsEdit  = false;
	IsReady = false;
	var TmpCon = new MdbConnection{
		SqlCon	= MdbCon.SqlCon,
		//...
	};
	TmpListe = new LstListe(TmpCon);
}	// End worker_DoWork

RunWorkerCompleted:

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){
	if(e.Cancelled) return;

	if(TmpListe.Count <= 0) return;
	ColGeraeteListe.Clear();			
	foreach(var _Item in TmpListe){
		ColGeraeteliste.Add(_Item);
	}
	ClvGeraeteliste.Refresh(); // CollectionViewSource
	IsReady = true;
}
private void refresh_GeraeteListe(){
	Worker.RunWorkerAsync();
	// ..			
}

private RelayCommand 	_CmdRefreshGeraeteliste;
public  ICommand	CmdRefreshGeraeteliste{
	get{
		return _CmdRefreshGeraeteliste ?? (_CmdRefreshGeraeteliste = new RelayCommand(
			param =>{
				TbxIsFocused = false;
				refresh_GeraeteListe();
				TbxIsFocused = true;
			},
			param => true));
	}
}

Das Problem ergibt sich dergestalt, dass die mittels Backgroundworker gefüllte temporäre Liste TmpListe innerhalb worker_RunWorkerCompleted oft NULL ist,
jedenfalls bei Aufruf von refresh_GeraeteListe() durch den Konstruktor. Wenn ich refresh_GeraeteListe() über das Command CmdRefreshGeraeteliste aufrufe, tritt das Problem scheinbar nicht auf.
Deklariert ist die TmpListe ja im ViewModel, gefüllt wird sie aber in einem anderen Thread als die Instanziierung des ViewModels. An der Stelle scheint mir der Hase im Pfeffer zu liegen. 😃
Ich würde mich freuen, könnte mir einer von euch ein wenig auf die Sprünge helfen.

Danke und Gruß
Jessimaus

17.08.2017 - 20:30 Uhr

Hallo Sir Rufo,

dass leuchtet mir ein. Vielen Dank für deine Erläuterung.

Gruß
jessimaus

16.08.2017 - 20:59 Uhr

Hi

@unconnected
Ja, hab ich. 😃 Benutze ich ja an diversen anderen Stellen in der Anwendung.

@Sir Rufo
Habe deine Lösung für mich angepasst und schon funktioniert es. 😉
Kannst Du in ein zwei Sätzen darlegen, warum das im TabControl nicht auf die 'herkömmliche Weise' funktioniert. Oder wo ich das nachlesen kann.

Vielen Dank an euch beide für die schnelle Hilfe.

Gruß
jessimaus

15.08.2017 - 15:45 Uhr

Hallo Leute,

ich habe ein TabControl mit zwei TabItems. Auf jedem dieser TabItems befinden sich diverse Text- bzw. ComboBoxen.
Bei Verlassen der letzten ComboBox des ersten TabItems möchte ich den Eingabefocus auf die erste Textbox des zweiten TabItems verschieben.

private void CbxServicetechniker_OnPreviewKeyDown(object sender, KeyEventArgs e){
	if(e.Key == Key.Enter){
		Tab_Index = 1;
		TbxIsFocused = true;
		e.Handled = true;
	}
}

Für das TabControl ist u.a. folgendes definiert:

<TabControl
	SelectedIndex="{Binding Tab_Index}"
	KeyboardNavigation.DirectionalNavigation="Continue">

Und für die Ziel-TextBox:

behaviors:BhvFocusExtension.IsFocused="{Binding TbxIsFocused, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"

Das zweite TabItem wird zwar aktiviert aber der Eingabefocus ist nicht vorhanden. Ich muss erst die Tab-Taste betätigen, um den Focus in die erste TextBox zu verschieben.
Hat jemand einen Tipp, was ich ändern bzw. hinzufügen muss, damit das ohne Tab-Taste funktioniert?

PS: Auch mit dem Holzhammer

TextBoxName.Focus();

funktioniert es nicht.

Danke und Gruß
jessimaus