Ich habe inzwischen selber eine Lösung gefunden.
Wenn ihr mal das selbe Problem haben solltet, ich habe es so gelöst:
using Outlook = Microsoft.Office.Interop.Outlook;
public static Outlook.MAPIFolder GetInbox()
{
Outlook.Application app = Globals.ThisAddIn.Application;
Outlook.MAPIFolder currentFolder = app.ActiveExplorer().CurrentFolder;
Outlook.Account account = GetAccountForFolder(currentFolder);
Outlook.MAPIFolder inbox = account.DeliveryStore.GetDefaultFolder (Outlook.OlDefaultFolders.olFolderInbox);
}
private static Outlook.Account GetAccountForFolder(Outlook.MAPIFolder folder)
{
// Obtain the store on which the folder resides.
Outlook.Store store = folder.Store;
// Enumerate the accounts defined for the session.
return
Globals.ThisAddIn.Application.Session.Accounts.Cast<Outlook.Account>().FirstOrDefault(
account => account.DeliveryStore.StoreID == store.StoreID);
}
Die GetAccountForFolder Methode gibt's von MS. Ich habe die For Schleife mittels LINQ ausgedrückt.
Danach wird irgendwann die Move Methode des MailItems aufgerufen. Das glaube ich ist hier nicht relevant.
Das Problem tritt auf, wenn mehrere Postfächer existieren.
Es wird eine E-Mail aus dem Postfach 2 ausgewählt und verarbeitet. Es wird aber immer in den Ordner des Postfachs 1 verschoben.
Nach etwas Debuggen habe ich rausgefunden, dass die Methode ActiveExplorer noch das richtige Postfach (also in diesem Bsp Postfach 2) zurück gibt. Bei der Session Property wird aber immer das Postfach 1 verwendet.
Wie kann ich denn eine E-Mail innerhalb eines Postfachs verschieben?
Ich hoffe ihr versteht was ich meine.
Ich habe dazu auch leider nichts gefunden, sondern nur die oben genannte Möglichkeit, wie ich an den Posteingang-Ordner komme.
Ich glaube das stimmt so nicht.
Ich dachte, dass .NET 4.0 eine Standalone Version ist und daher nicht .NET 2.0, 3.0, 3.5 mitliefert.
.NET 3.5 ist nur ein "Update" und bringt deshalb 2.0 und 3.0 mit. Daher kann man mit .NET 3.5 auch .NET 2.0 Applikationen ausführen?
.NET 2.0 war auch eine Standalone Version und es konnten keine .NET 1.0 Applikationen ausgeführt werden?
Natürlich kann zusätzlich zu .NET 4.0 das ältere 3.5 installiert werden.
.NET 4.5 ist wieder nur ein "Update" und deswegen wird .NET 4.0 mitgeliefert.
Korrigiert mich bitte, wenn das falsch ist.
Ich dachte das mal gelesen zu haben ...
ich habe ein Problem und finde Google keine Lösung.
Ich schreibe ein kleines Programm, dass mit einem SystemFileWatcher ein Verzeichnis überwacht in dem TIF Dateien abgelegt werden. Die Tif Datei soll dann in einem neuen Fenster angezeigt werden.
PicViewer ist das neue Fenster.
Hier gibt's die Methode ShowFullScreen.
public void ShowFullScreen(string filename)
{
using (FileStream fs = new FileStream(filename, FileMode.Open))
{
imgPicture.Source = BitmapFrame.Create(fs, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
Show();
Topmost = true;
WindowState = WindowState.Maximized;
}
Es tritt eine IOException auf im Konstruktor des FileStreams.
Hier der StackTrace:
Stapel:
bei System.IO.__Error.WinIOError(Int32, System.String)
bei System.IO.FileStream.Init(System.String, System.IO.FileMode, System.IO.FileAccess, Int32, Boolean, System.IO.FileShare, Int32, System.IO.FileOptions, SECURITY_ATTRIBUTES, System.String, Boolean, Boolean)
bei System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.IO.FileAccess, System.IO.FileShare, Int32, System.IO.FileOptions, System.String, Boolean)
bei System.IO.FileStream..ctor(System.String, System.IO.FileMode)
bei FaxViewer.PicViewer.ShowFullScreen(System.String)
bei FaxViewer.MainWindow.ShowPicViewer(System.String)
bei FaxViewer.MainWindow+<>c__DisplayClass3.<FileSystemWatcherOnCreated>b__1()
bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
bei MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
bei System.Windows.Threading.DispatcherOperation.InvokeImpl()
bei System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(System.Object)
bei System.Threading.ExecutionContext.runTryCode(System.Object)
bei System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object)
bei System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
bei System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
bei System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
bei System.Windows.Threading.DispatcherOperation.Invoke()
bei System.Windows.Threading.Dispatcher.ProcessQueue()
bei System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
bei MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
bei MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
bei MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
bei System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
bei MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
bei MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
bei System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
bei System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
bei System.Windows.Threading.Dispatcher.Run()
bei System.Windows.Application.RunDispatcher(System.Object)
bei System.Windows.Application.RunInternal(System.Windows.Window)
bei System.Windows.Application.Run(System.Windows.Window)
bei System.Windows.Application.Run()
bei FaxViewer.App.Main()
Das merkwürdige ist:
Ich entwickle auf einem Win7 PC mit VS2010. Hier tritt das Problem nicht auf.
Auf einem Win XP SP3 Rechner tritt die Exception nach dem 2. Mal auf.
Also das erste Bild wird angezeigt, beim Zweiten tritt die IOException auf.
Auf beiden PCs ist .NET 4.0 Extended installiert. Kompilieren tue ich das Projekt gegen das .NET 4.0 Client Profile Framework.
Ich habe auch schon mit BitmapSource mit CacheOption.OnLoad, BeginInit, EndInit.
Jedesmal das selbe Ergebnis.
Windows 7 hat's jedesmal funktioniert.
Ich hab auch schon gelesen, dass es ein Bug in der Windows Imaging Component ist. Eine Lösung habe ich dazu noch nicht gefunden.
Hat jemand eine Idee wie ich das lösen kann?
Danke
caldi
ich habe erst kürzlich auch Interprozesskommunikation benötigt.
Das Zyan Framework von Rainbird kann das ebenfalls bewerkstelligen und ist in der Anwendung sehr einfach.
Ich konnte damit Kommunikation von zwei Anwendungen schnell und problemlos umsetzen.
ich brauch mal wieder eure Hilfe.
Ich habe zwei unabhängige Addins mit VS2010 und VSTO für MS Outlook 2010 geschrieben.
Beide Addins sollen auf den selben Ribbon Tab, aber in unterschiedliche Gruppen dargestellt werden.
Die Ribbons habe ich bisher mit dem Designer bearbeitet und nicht in XML konvertiert.
Bisher werden 2 Ribbon Tabs angelegt, die den selben Namen haben, und auf jedem Tab gibt's eine Ribbon Gruppe für das jeweilige Addin.
Natürlich habe ich schon gegoogelt, der einzige Hinweis, den ich gefunden habe, das Problem mit dem Designer zu lösen ist hier.
Allerdings kann ich die ControlId nicht verändern.
Wisst ihr vielleicht wie ich das Problem mit dem Designer lösen kann oder muss ich wirklich das Ribbon in eine XML konvertieren?
ich habe testweise die Benutzerdefinierte Aktion "Installieren" gelöscht.
Dann wird der Dienst tatsächlich nicht registriert. Getestet habe ich es ohne dass der Dienst davor installiert war.
Daher verstehe ich nicht, warum der erste Lösungsansatz von Grumbler85 nicht funktionierte.
Ich habe außerdem probiert eine Condition bei der Installieren Aktion anzulegen.
Eine MSDN-Dokumentation habe ich dazu leider nicht gefunden.
Folgende Condtions habe ich bereits probiert:
(Not Installed) OR PREVIOUSVERSIONSINSTALLED
Not Installed
NOT Installed
Ich habe gelesen, dass die Anweisung case-sensitive ist.
Vermutlich sind die Bedingungen falsch und deswegen wird die Benutzerdefinierte Aktion trotzdem ausgeführt.
Habt Ihr vielleicht eine Idee, wie die Condition richtig heißen muss?
Ich habe gerade auch nochmal probiert, die Commit und Install Methode mit einem return zu beenden ohne die Base Methode oder irgend einen anderen Code auszuführen.
Leider ebenfalls ohne Erfolg.
Es scheint als würde die Dienst Registrierung nicht hier statt finden.
irgendwie scheint es gar nicht zu klappen.
Ich habe jeweils einzeln die Commit Methode und die Install Methode so überschrieben, dass die base Methode nur dann aufgerufen wird, wenn der Dienst nicht bereits installiert ist.
Ich habe es mit beiden Methoden gleichzeitig versucht.
Jedesmal habe ich die Major Versionnummer erhöht und den ProductCode verändert (UpdateCode ist gleich geblieben). Der Dienst war zum Zeitpunkt der Installation aus.
Trotzdem kam jedesmal die selbe Fehlermeldung, dass der Dienst bereits installiert sei.
Ich bin etwas ratlos, an was es noch liegen könnte?
Ok, danke :)
Du hast Dich vorher so sicher angehört, da bin ich gar nicht auf die Idee gekommen, dass ich eine andere Methode probieren könnte zu überschreiben ..
danke für den Tipp, ich habe versucht das umzusetzen leider funktioniert es nicht.
Zusätzlich zur Install Methode habe ich die OnAfterInstall Methode überschrieben um den Dienst nach der Installation automatisch zu starten.
So sieht der Code aus:
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
{
InitializeComponent();
}
public override void Install(IDictionary stateSaver)
{
if(!ServiceAlreadyInstalled(serviceInstaller.ServiceName))
base.Install(stateSaver);
}
private static bool ServiceAlreadyInstalled(string serviceName)
{
ServiceController[] allServices = ServiceController.GetServices();
return allServices.Any(sc => sc.ServiceName == serviceName);
}
protected override void OnAfterInstall(IDictionary savedState)
{
base.OnAfterInstall(savedState);
ServiceController sc = new ServiceController(serviceInstaller.ServiceName);
int count = 10;
if (sc.Status == ServiceControllerStatus.Stopped)
{
sc.Start();
while (sc.Status == ServiceControllerStatus.Stopped && count > 0)
{
Thread.Sleep(1000);
sc.Refresh();
count--;
}
}
}
Habe ich vielleicht irgendwas falsch gemacht?
Der Fehler bleibt der Selbe...
Das macht das Setup Projekt für mich.
Ich habe unter Ansicht->Benutzerdefinierte Aktionen das Dienst-Projekt zu allen 4 Kategorieren (Installieren, Commit ausführen, Rollback, Deinstallieren) hinzugefügt.
Damit wird der Dienst registriert.
danke für Eure Antworten.
Ich habe gerade probiert die Versionsnummer an der dritten Stelle zu erhöhen.
Den ProductCode habe ich geändert. UpgradeCode ist gleich geblieben.
Leider ohne gewünschtem Ergebnis.
Beim Installieren kommt der selbe Fehler.
Könnte ich die Dienst Registrierung mit einem CustomInstaller bei bereits vorhandener Installation überspringen?
ich habe ein Setup Projekt gemacht, das einen Windows Dienst installiert. Das klappt auch.
Bei einem Update habe ich Assembly und die Setup Version erhöht.
Folgende Eigenschaften habe ich beim Setup gesetzt:
DetectNewerInstalledVersion = True
RemovePreviousVersions = True
Wenn ich aber das geupdatete Setup auf einer Maschine ausführe, auf der bereits der Windows Dienst installiert ist, kommt während dem Setup die Fehlermeldung "Der angegebene Dienst ist bereits vorhanden".
Ich hätte gehofft, das Setup entfernt die alte Installation bevor die neue Version installiert wird.
Oder überschreibt die alte Version mit der Neuen?
Vielen Dank, jetzt klappt es.
An die DefaultView Eigenschaft hatte ich nicht gedacht.
Ich hätte gehofft, dass das die BindingSource für mich erledigt..
Jetzt habe ich für das 2. Binding ein extra DataView angelegt und es funtioniert.
verwendetes Datenbanksystem: <MS SQL Server Compact 3.5>
Das Szenario ist wie folgt:
Ich halte Daten in einem DataTable.
Zum Einen habe ich das DataTable mittels BindingSource an ein DataGridView A gebunden.
Mit einer TextBox kann der Benutzer die Daten filtern.
Ich reagiere auf das TextChanged Event der TextBox und ändere die Filter-Eigenschaft der BindingSource.
Zum Anderen ist das DataTable (nicht die BindingSource) direkt an eine DataGridViewComboBoxColumn eines zweiten DataGridViews B gebunden.
Wenn der Benutzer einen Suchtext in die TextBox eingibt, wird wie erwartet die entsprechenden Daten im DataGridView A angezeigt.
Gleichzeitig greift der Filter aber auch in der DataGridViewComoBoxColumn.
Das ist aber nicht beabsichtigt. In der DataGridViewComboBoxColumn sollen ungefiltert alle Werte aus der DataTable angezeigt werden.
Ich hätte erwartet, dass die Filterung nur durch die BindingSource "sichtbar" ist und das DataTable unverändert bleibt.
Ich hoffe Ihr versteht, was ich meine ...
Habe ich was falsch gemacht, oder wird der Filter wirklich auf das DataTable projeziert?
Warum die Wiedergabe verzögert weiß ich nicht, aber du registrierst für jeden Aufruf der PlaySound-Methode ein neues Event für LoadCompleted.
Evtl. verzögert der Player dadurch schon ...
ich hatte ein ähnliches Problem und habe mir vom Conrad eine Relaiskarte gekauft.
Die Relaiskarte kannst Du mit C# ohne größere Probleme ansteuern. Die Befehle sind gut dokumentiert.
Die hier sollte auf deine Bedürfnisse zutreffen: Relaiskarte
Ich habe die mit 24V gekauft und die ersten Tests liefen erfolgreich.
Ein Beispiel Code in VB liegt auch bei.
Der ist auch im Download Bereich beim Conrad zu finden.
diese Lösungen hatte ich auch schon gefunden.
Nur dachte ich, dass diese nicht zum Ziel führen:
Das CMS erkennt im Moment den Typ und kann ein Preview der EMail anzeigen.
In den Beispielen werden ja nur die Eigenschaften der Email serialisiert und nicht das ganze MailItem?
Ich war der Meinung, dass das ein Unterschied ist und das CMS den Typ daher nicht erkennt?
Oder liege ich damit falsch?
Mittels Outlook Addin soll eine Email in ein ContentManagmentSystem geladen werden.
Die API des CMS erwartet das hochzuladende Objekt als byte[].
Ich habe bisher leider nichts gefunden, wie ich ein Mailitem in ein byte[] konvertieren kann.
MailItem ist nicht mit dem Attribut Serializable gekennzeichnet.
Im Moment nutze ich die SaveAs Methode des MailItems um ein Temp-File zu schreiben, dass ich anschließend mit einem FileStream wieder einlese. Danach lese ich den Stream in ein byte[] ein.
Ich habe bei Google nur das Stichwort IPersist Interface gefunden.
Allerdings weiss ich leider überhaupt nicht, wie ich ein COM Interface implementieren kann.
Gibt es vielleicht eine leichtere Möglichkeit oder könnt ihr mir ein Tipp geben, wie ich das IPersist Interface richtig implementiere?
Das liegt daran, dass Dein ListView in der Form1 den Zugriffsmodifizierer "Private" hat.
Daher kannst du nur innerhalb der Klasse Form1 auf das ListView Objekt zugreifen.
ich habe eine Bibliothek geschrieben zur Lizenzierung.
Bei der Installation soll ein Eintrag in der Registry statt finden und ein Lizenzfile angelegt werden.
Das klappt auch wunderbar.
Mein Problem betrifft das ErrorHandling.
Sollte z.B. das Schreiben in die Registry fehlschlagen, dann macht das Setup nicht mehr weiter, zeigt aber auch keinerlei Fehlermeldung an.
Hier ein Codeausschnitt:
(Die Methode ist gekürzt. Es finden zusätzlich ähnliche Überprüfungen statt, die als Beispiel ohne Relevanz sind. Variablen wie file oder regPath existieren. Es geht lediglich um die Fehlermeldung, die trotz der InstallException nicht angezeigt werden.)
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
try
{
string file = this.Context.Parameters["FilePath"];
if (string.IsNullOrEmpty(file))
throw new ArgumentException();
RegistryKey reg = Registry.LocalMachine.CreateSubKey(regPath, RegistryKeyPermissionCheck.ReadWriteSubTree);
if (reg == null)
throw new AuthenticationException("user has no admin rights");
}
catch (ArgumentException)
{
throw new InstallException("Fehler.");
}
catch (AuthenticationException)
{
throw new InstallException("Rechte.");
}
catch(Exception ex)
{
throw new InstallException(ex.Message);
}
}
Ich bin nach dem Beispiel in InstallException Class vorgegangen.
Wenn aber eine Ausnahme auftritt, dann macht der Installer nichts mehr, der Fortschnitt bleibt unverändert und es kommt keine Fehlermeldung.
Wisst Ihr vielleicht was ich hier falsch mache?
Ich sehe keinen Unterschied zum Beispiel von MSDN.
Ich habe zu Testzwecken auch direkt als erste Anweisung der Install()-Methode eine InstallException geworfen, allerdings mit dem selben Ergebnis.
Empfehlen kann ich auch Zyan, das von Rainbird entwickelt wird.
Es verwendet zwar .NET Remoting als Technologie, bietet aber Einsteigern eine sehr einfache Möglichkeit ein Server/Client Szenario zu verwirklichen...
ich tausche eigtl. nicht das ganze DataTable aus. (oder mir ist es nicht bewusst)
hier die Methode, die den neusten Eintrag vom Server lädt:
private void LoadLatestStatusFromServer()
{
// Wenn der Aufruf nicht aus dem GUI-Thread kommt ...
if (InvokeRequired)
// Aufruf an den GUI-Thread delegieren
Invoke(new Action(LoadLatestStatusFromServer));
else
{
// Statustabelle vom Server abrufen
DataSet.StatusDataTable table = AppServer.Service.GetLatestStatus();
// Vom Server abgerufene Statusdaten ins lokale DataSet laden
this._localDataSet.Status.Merge(table);
}
}
Die Tabelle wird aus mit dieser Methode nie verändert. Daher finde ich es komisch, wenn die Indices nicht übereinstimmen?!
EDIT:
Also ich habe das jetzt so gelöst:
Bei dem Event, mit dem der Server den Client benachrichtigt, dass ein neues Element vorhanden ist, schreibe ich das neue Element in eine Liste (die DataRow).
In einem Timer rufe ich die List.RemoveAll() Methode auf.
Das Prädikat, das ich der RemoveAll() Methode übergebe prüft, ob die die Zeile älter als x Sekunden ist (ich speichere ein DateTime in der Zeile).
Dann suche ich die Zeile in der BindingSource anhand der Zeit und Resete dann die Zeile der BindingSource.
Dann wird eben True bzw. False zurückgegeben, damit es ein Prädikat ist.
In der Paint Cell Methode prüfe ich natürlich, ob das zu zeichnende Objekt in der Liste steht und wähle dann eine andere Farbe.
Ich hoffe, das ist keine übermäßig unsaubere Lösung :)
Danke für Deine Hilfe, das hat mich auf die richtige Fährte gebracht ! :)
danke für Deine Antwort.
Die Idee finde ich gut. Leider klappt das bei mir noch nicht so ganz:
Den ListChangeType.ItemAdd erhalte ich nie. Nur Reset.
Meine Server Applikation benachrichtigt alle Clients, wenn ein neuer Eintrag vorhanden ist.
Die Clients holen sich dann diesen in Form einer DataTable (mit nur 1 Eintrag; dem Neusten) und mergen das Table dann in das lokale DataSet.
Nachdem ich aber ohnehin ein Event habe, das mich über einen neuen Eintrag informiert und ich diesen dann abhole, kann ich den neuen Eintrag ja auch hier abfangen und in ein Dictionary schreiben.
Das klappt auch.
Mein Problem ist jetzt, dass ich bei der Timer Methode, das ja das Alter prüft und dann die zu alten Einträge aus dem Dictionary entfernt, nicht weiss, wie ich nur diesen einen Datensatz neuzeichnen lassen kann. Das würde mir nämlich gut gefallen, dass nicht dass ganze DGV gezeichnet werden muss, sondern eben nur die paar neuen Einträge.
Kann ich da irgendwie eine Beziehung herstellen von einer DataRow zu der entsprechenden Zeile?
Ich habe das so versucht:
Beim eintreten des neuen Eintrag-Events wird die DataRow in eine List<DataRow> geschrieben.
Der Timer tickt alle 500ms.
Die Timer Methode sieht so aus:
private void neuerEintragTimer_Tick(object sender, EventArgs e)
{
foreach (DataRow dr in this.newStatus)
{
DateTime time = (DateTime)dr["Zeit"];
if (time.AddSeconds(5) > DateTime.Now)
{
this.newStatus.Remove(dr);
int index = this._localDataSet.Status.Rows.IndexOf(dr);
this.StatusBinding.ResetItem(index);
}
}
}
Allerdings ist der index den ich erhalte immer um 1 größer als die Anzahl der BindingSource.
Das verstehe ich nicht ganz, weil der gefundene Index ziemlich klein sein sollte und die BindingSource gar nicht weniger Elemente enthalten kann als das DataSet.
Das DataSet.Status ist ja die DataSource dieser BindingSource.
Finde ich sehr merkwürdig?
Habe ich was falsch gemacht?
ich habe ein Problem.
Ich möchte gerne, dass eine neue Zeile eines DataGridViews für x Sekunden farblich hervorgehoben wird.
Ich weiss nicht so recht wie ich das anstellen kann.
Das DataGridView hat ja ein RowsAdded Event.
Das würde sich ja hier anbieten?
Für jeden neuen Eintrag benötige ich einen eigenen Timer der z.B. nach 5s tickt, weil ja jede neue Zeile individuell behandelt werden soll?!
Wie kann ich jetzt beim Tick des Timers genau auf diese eine Zeile zugreifen?
Die neuste Zeile ist es ja möglicherweise nicht, weil während dieser 5s schon wieder eine Neue dazu gekommen ist.
Kann ich das den EventArgs mitgeben?
Oder übergibt man sowas z.B. in das Timer.Tag Attribut?
Die DataGridViewRowsAddedEventArgs haben ja die Eigenschaft RowIndex.
Wobei, wenn eine neue Zeile hinzugefügt wird, der RowIndex ja verfäscht wird?
Ich habe mehrere DataGridViews und möchte bei jedem die neuen Zeilen hervorheben.
Woher weiss ich in der Tick Methode des Timers, welches DGV Auslöser war?
Oder muss ich für 3 DGVs alles 3x bauen?
Oder wäre es besser ein neu Zeichnen des DGV mittels Timer alle x Sekunden auszulösen und in dem Cell Painting Event die Zeitdifferenz prüfen und dann ggf. farblich hervorheben.
offensichtlich habe ich doch etwas falsch gemacht.
Aufgrund Deines Tipps habe ich Dein Zyan Projekt in meine Projektmappe eingebunden und die Verweise aktualisiert.
Der Fehler tritt nicht mehr auf.
In das DataTable (das ist die DataSource des DataGridViews) wird beim Event anstandslos der Eintrag hinzugefügt. Damit habe ich auch kein Problem mit dem Zugriff auf die GUI und dem Event auslösenden Thread.
Auch wenn's nicht direkt hier her gehört:
Beim Start des Clients werden alte Einträge vom Server geschickt und in den DataTable eingetragen. Der DataGridView zeichnet das auch sofort.
Wenn ich über das Event in die DataSource den neusten Eintrag hinzufüge, dann wird das DataGridView nicht neu gezeichnet. Erst beim Scrollen wird neu gezeichnet. Der Inhalt wird aber gesetzt, weil das neue Element nachdem Neuzeichnen vorhanden ist.
Meine Frage ist jetzt, warum das so ist, bzw. wie man das löst?
Mit .Update() habe ich es versucht, aber ohne Erfolg.
Zitat
Sorry, da verstehe ich das Problem leider nicht.
Ich hätte hier zuerst probiert das so zuschreiben:
OnObjectAddedEvent(NotificationEventArgs.Empty);
Allerdings meckert der Compiler, weil NotificationEventArgs.Empty den Typ EventArgs zurück gibt, aber die Methode OnObjectAddedEvent den Typ NotificationEventArgs erwartet.
Mache ich da was falsch?
Oder ist die Lösung von unten genauso sauber?
Meine Klasse, die das Event beinhaltet sieht so aus:
private static List<myObject> m_objectHistory = new List<myObject>();
public event EventHandler<NotificationEventArgs> ObjectAddedEvent;
protected virtual void OnObjectAddedEvent(NotificationEventArgs e)
{
if (ObjectAddedEvent != null)
{
ObjectAddedEvent(this, e);
}
}
public bool addObject(string kennung, string status)
{
try
{
m_objectHistory.Add(new myObject(kennung, status));
OnObjectAddedEvent(new NotificationEventArgs(""));
// Hier kann ich nicht NotificationEventArgs.Empty mitgeben, weil der Getter den Typ
// EventArgs zurück gibt. Und das darf ich ja nicht?
return true;
}
catch (Exception)
{
return false;
}
}
Auf dem Server schaut meine Event Veröffentlichung so aus:
HttpCustomServerProtocolSetup protocolSetup = new HttpCustomServerProtocolSetup(Properties.Settings.Default.PORT, userMng, true);
ZyanComponentHost host = new ZyanComponentHost("Test", protocolSetup);
host.StartNotificationService();
history.ObjectAddedEvent += host.PublishEvent("ObjectAddedEvent");
Auf dem Client habe ich das Event abonniert:
HttpCustomClientProtocolSetup protocolSetup = new HttpCustomClientProtocolSetup(true);
ZyanConnection connection = new ZyanConnection("http://localhost:10000/Test", protocolSetup, credentials, true); //credentials sind weiter oben definiert, das funktioniert bereits
history = connection.CreateProxy<IHistory>();
connection.SubscribeEvent("ObjectAddedEvent", proxy_ObjectAddedEvent);
Die Event-Methode soll in ein DataGridView das gerade hinzugefügte Element schreiben:
Kann ich hier mittels sender auch auf das Remote Objekt History zugreifen und direkt die lastEntry.. holen?
Im Moment ist history so global definiert, dass die Methode Zugriff auf den Proxy hat.
Wenn ich die Event-Methode im Debug durchlaufe, dann wird keine Exception geworfen, aber am Schluss, kurz bevor die Methode beendet werden würde, kommt von VS der Hinweis, dass eine Quelldatei fehlt:
Aufruflistenort:
Zyan.COmmunication.dll!Zyan.Communication.Notification.NotificationReceiver.FireNotifyEvent(object sender, Zyan.Communication.Notification.NotificationEventArgs e) Zeile 52
Quelldateiinformationen:
Quelle für "C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" wird gesucht. Checksum: MD5 {1c 38 a5 41 bd dd 7c 84 92 85 dd 50 20 e2 ba 2a}
Die Datei "C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" ist nicht vorhanden.
"C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" wird in Skriptdokumenten gesucht...
"C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" wird in Projekten gesucht.
Die Datei wurde nicht in einem Projekt gefunden.
In Verzeichnis "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src\" wird gesucht...
In Verzeichnis "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\atlmfc\src\mfc\" wird gesucht...
In Verzeichnis "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\atlmfc\src\atl\" wird gesucht...
In Verzeichnis "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\atlmfc\include\" wird gesucht...
In den Einstellungen zum Debuggen von Quelldateien für die aktive Lösung ist angegeben, dass der Benutzer nicht zum Suchen der Datei aufgefordert wird: C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs.
Die Quelldatei "C:\Code\Zyan\source\Zyan.Communication\Notification\NotificationReceiver.cs" wurde nicht gefunden.
Edit:
Die Fehlermeldung krieg ich auch, bei der Authenticate() Methode.
Allerdings tritt der Fehler nur dann auf, wenn die Zyan.Communication.pdb Datei im Verzeichnis liegt.
Ist diese nicht vorhanden, funktioniert die Authenticate() Methode.
Bei dem Event auf dem Client bleibt das Programm jedoch auch ohne PDB Datei stehen, nur eben ohne Fehler Hinweis.