Die Male wo ich mit Bindings Probleme hatte, bin ich irgendwie durch ewiges debuggen und ausprobieren dann zu einer Lösung gekommen oder auch nicht. Allgemein kann ich leider nichts dazu sagen.
Lass dir mal alle Möglichen Events in der Console oder in ein LogFile ausgeben. Setter/Getter-Entry/Exit, MouseDown, MouseUp, CheckedChanged, PropertyChanged und schau ob dir dabei etwas auffällt.
Manchmal wird ein Getter nicht abgefragt, wenn er aus einem Setter aufgerufen wurde. - Dies passiert aber normalerweise nur wenn es sich ums selbe Property handelt.
Mittels dem logging solltest du aber konkret feststellen könne wie das Program sich genau verhält und dazu kann man dann vielleicht eine konkretere Aussage treffen.
Lg, XXX
//Edit: Evt. hilft ein BeginInvoke um A/B=false zu legen um diese Ausführung kurz Zeitverzögert auszuführen.
Die Bindings schauen an und für sich ok aus aber ich vermute den Hund irgendwo im Bindingsystem von Windows.Forms begraben. Ich hab schon so oft Schwierigkeiten damit gehabt weil das System einfach total unverständlich reagiert. Manchmal/Oft muss man ein BindingManager.EndEdit/Accept oder ein Binding.WriteValue() im Codebehind nachsetzen, damit die Werte auch wirklich greifen. Wirklich verstanden hab ichs nie und ich bin auch froh, dass dies bei WPF nun wesentlich besser läuft.
Es gibt eine coole Möglichkeit unter TSQL alle eingefügten IDs automatisch am Ende des Inserts auszugeben worauf ich erst vor kurzem gestoßen bin:
create table test(Id uniqueidentifier primary key default(newid()), Name varchar(max))
go
insert test(Name)
output inserted.Id
select Name
from
(
select 'Max' as Name
union all
select 'Moritz' as Name
union all
select 'Gretchen' as Name
union all
select 'Heidi' as Name
)tmp
Bei WPF kann man auch negative Margins setzen... das könnte hier zB funktionieren indem du den weißen Rand einfach unter den schwarzen Rand außen drunterschiebst. Aber ich befürchte das negative Margins bei Windows.Forms nicht möglich sind.
Als alternativen (schmutzigen) Workarround kannst du noch schwarze Panels über den weißen Rand legen.
TabControl wie jedes andere Control unter Windows.Forms erbt von System.Control was wiederum die Eigenschaft BackColor besitzt. (Ich vermute aber dennoch, dass dies den äußeren Rand hier nicht verändern wird)
Das deine Grafik einen grauen Rand hat, ist ausgeschlossen? Wenn du also kein Hintergrundbild in deinem Panel setzt, bleibt der graue Rand auch da? Ist evt. ein Margin auf deinem Panel eingestellt?
Das TableLayoutPanel sowie jedes andere LayoutControl zeichnet normalerweise nichts selbstständig rein und wenn der Hintergrund des TablLayoutPanels selbst schon Schwarz ist, dürfte kein grauer Rand da sein außer er wird vielleicht durch dein Panel oder dein Backgroundimage verursacht.
die Compact Variante bietet dir serverlosen Zugriff auf eine Datenbankdatei. Du kannst dir das auch wie ein Access-File vorstellen. Sowas macht vielleicht bei einem kleinen Kassaprogram in einem Blumenladen noch Sinn aber sobald mehr als dieser eine Computer inkl. Synchronisierung über mehrere Datenbanken im Spiel ist -> vergiss compact. (aus meiner Sicht)
Das SyncFramework kenne ich nicht aber ein paar Tabellen von Server A nach Server B zu kopieren/synchen geht auch schnell und einfach indem die Server als LinkedServer einrichtet und entsprechende Insert, Update, Delete Statements dafür bastelt.
Wieso wird hier so lange herumphilosophiert, wenn eindeutig klar ist, dass die ListBox schlichtweg falsch verwendet wird. (Sieht man im 1. Post):
Weil:
- In einer ListBox, dass ItemTemplate bereits einem ListBoxItem gehört. Man erzeugt prinzipiell nie eigene ListBoxItems - das macht die ListBox für dich und wendet darauf dann dein DataTemplate an. Daher macht auch das Setzen der IsSelected Property auf dein ListBoxItem keinen Sinn, weil es einfach das Falsche ist.
- Um es richtig zu machen, musst du einen Style fürs ListBoxItem definieren und dort das Binding für IsSelected reinpacken.
Das ganze hättest du aber auch mit 5 min. Googlen auch gefunden.
Oder häng dich mit dem Visual Studio Debugger(notfalls Remotedebugger) ins Programm wenn es nicht mehr weiter tut und prüfe falls möglich den Zustand auf diese Weise.
Lg, XXX
//Edit: Übrigens könntest du dein Programm ja auch einfach als Konsolenanwendung oder gleich direkt im Debugger laufen lassen(falls VS am Zielrechner installiert ist) um es einfacher/anders zu testen.
Falls ich falsch liege bitte ich darum mich eines besseren zu belehren.
Ja, Du liegst falsch.
Gerade das ständige pollen ist deutlich resourcefressender als diese kleine Queue, bei der der Sql Server selber entscheiden kann wann er dich benachrichtigt.
Diese "Rückruf" Funktionalitäten sind gerade deshalb überhaupt in die verschiedenen Sql Server eingebaut worden.
Laut MSDN ist das aber nicht die empfohlene Vorgehensweise:
SqlDependency wurde zur Verwendung in ASP.NET oder in Diensten der mittleren Ebene entworfen, in denen eine relativ kleine Anzahl von Servern aktive Abhängigkeiten für die Datenbank aufweisen.Das Objekt wurde nicht für Client-Anwendungen entworfen, in denen für Hunderte oder Tausende Client-Computer SqlDependency-Objekte für einen einzelnen Datenbankserver eingerichtet sind.Wenn Sie eine Anwendung entwickeln, in der Sie zuverlässige Sub-zweite Benachrichtigungen erfordern, wenn Datenänderungen, die Abschnitte Planen einer effizienten Abfragebenachrichtigungsstrategie und Alternativen zu Abfragebenachrichtigungen im Planen für Benachrichtigungen Thema in der SQL Server-Onlinedokumentation überprüfen.
Bzgl. der Items die trotzdem selektiert bleiben fällt mir leider gerade nichts mehr dazu ein.
Bzgl. der Vorgehensweise glaub ich, dass das Geschmackssache ist: Ich hab zum Beispiel mal eine Filterfunktion umgesetzt, die sich nur die sichtbaren Items merkt. Wenn der Filter wieder aufgelöst wird, sind nur die zuletzt markierten Elemente wieder markiert.
Falls das mit den virtuellen Items und dem IsSelected nicht hinhauen mag, bleibt dir denke ich nicht mehr viele Optionen.
Eine wäre, die nicht-funktionierende Logik selber nachzufrickeln. Zb. Bei einem ItemSelected auch noch prüfen ob die Shift Taste gedrückt war usw. Aber das ist nicht wirklich eine schöne Lösung. Oder du findest ein anderes Control das damit besser zurecht kommt.
ich habe das selber noch nie benötigt sondern nur ein Beispiel für dich im Netz gegoogelt. Was für ein komisches Verhalten bemerkst du denn? Mir fällt bei deinem Codeschnippsel nur auf, dass du immer alle Items durchiterierst und IsSelected setzt. Vielleicht ändert sich ja das Verhalten schon, wenn du nur die "AddedItems" und "RemovedItems" aus der SelectionChangedEventArgs-Klasse behandelst.
Bau einmal in deiner WorkAuto Methode oder nur um die DoIt Methode ein try-catch und behandle etwaige Fehler. Wenn ein Fehler in einem anderen Thread passiert, muss das nicht bedeuten, dass das Service deswegen beendet wird jedoch der Thread und die Schleife werden dadurch mit Sicherheit beendet sein.
Bau Logging ein und schau, ob das Program nach 6 Std. noch immer die Schleife sauber abarbeitet bzw. falls nicht, solltest du sehen bis wohin es zuletzt gekommen ist.
wenn du nicht weißt was es dir bringen soll, wieso denkst du dann ernsthaft darüber nach?
Wenn man schon so lange im Berufsleben steht zahlt sich ein Studium am selben Sektor(also Informatik) mMn. überhaupt nicht aus. Außer du strebst eine Position/Stelle an, die du ohne Studium nicht oder nur schwer bekommen würdest. (Lehre, Banken, Staatliche Betriebe(zumindest ist das angeblich in AT so))
Ich habe mir vor ein paar Jahren die selbe Frage gestellt und mich dann dagegen entschieden. Außer, dass ich im Ausland evt. leichter Jobs damit finden würde, habe ich für mich keinerlei Vorteile gesehen. Lieber nutze ich die Zeit anderwertig und lerne zB Sprachen.
Ich habe das behauptet. Ich selbst und auch in meinem Freundeskreis haben sich viele nach langem verweigern dann doch "weichklopfen" lassen und sind Facebook beigetreten. Wenn man sich auch mal daran gewöhnt hat ist es schon eine Hürde zu sagen - ich brauch das nicht mehr. Das sieht zur Zeit ähnlich aus wie mitn Handy - jeder "braucht" eines und ohne ist man aufgeschmissen, weil alle Kontakte da drinnen verwaltet werden und der größte Teil der Kommunikation darüber läuft. - Ich habe meinen Account mittlerweile aber wieder gelöscht.
Zitat von Abt
Wenn jemand nicht auf Facebook sein möchte: dann lasst halt.
Es geht hier nicht darum ob jemand dabei sein möchte oder nicht sondern, dass Facebook gewissenhaft mit den Daten der User umgeht. Die Idee hinter einer solchen Plattform sind ja völlig legitim und es hat einen haufen Vorteile für gewissen User um in Kontakt mit anderen zu bleiben.
Zitat von Abt
Keiner wird gezwungen, die korrekten Daten zu hinterlegen. Ich bin auch drin - aber weder mit öffentlich sichtbaren Profilfoto noch mit echtem Namen. Nicht mal mein angegebenes Geburtsdatum ist korrekt.
Es steht jedem ja frei zu posten was er will - du schränkst dich hier eben ganz besonders ein.
Zitat von Abt
Alle Features, die Facebook für andere bereitstellt (automatisches Markieren in Fotos etc...) sind bei mir deaktiviert.
Und jedes weitere Feature wird standardmäßig ohne zu fragen aktiviert. - sowas sind zum Beispiel Themen von europe-v-facebook.
Zitat von Abt
Hab absolut kein Mitleid mit den Leuten, die wegen Fotos nachher irgendwo angesprochen werden und wundern sich dann. Hirn einschalten muss man überall...
Es geht hier ja nicht um die Leute die gedankenlos ihr intimstes Privatleben veröffentlichen sondern um die Daten, die Facebook ohne wissen des Users aquiriert und weiterverarbeitet. - Mehr Transparenz ist gefragt; Nicht das vollständige Abstellen oder was weiß ich...
ich wollte auf diese Aktion hinweisen, welche sich zum Ziel gesetzt hat gegen Facebook und ihre Datenschutzrichtlinien speziell im Bezug auf das Europäische Recht vorzugehen.
Der Initiator, Max Schrems, hat aus meiner Sicht schon unglaublich viel erreicht und kämpft noch weiterhin für mehr Transparenz und Klarheit über die Verwendung der gesammelten Daten bei Facebook.
Facebook ist bereits so groß ist und viele in unserem Umfeld sind darauf vertreten, sodass eine gewisse Zwanghaftigkeit besteht, dem Verein beizutreten um kein Außenseiter zu sein. Bei jungen Menschen trifft das dabei sicherlich noch viel mehr zu als bei Erwachsenen und die kennen sich genau am wenigsten mit dem Thema aus.
Homepage Ziele der "Organisation". Youtube Seite mit Interviews und anderen Beiträgen zu dem Thema.
Ich kann nicht mehr sagen warum ich zB die letzten zwei Events auch abboniert habe aber es war anscheinend notwendig - du kannst dich ja damit spielen.
Die Berechnung hab ich dann so gestaltet:
private void RefreshControlSize()
{
if (!_autoSize) return;
int height = 0;
int width = 0;
foreach (DataGridViewRow row in Rows)
height += row.Height;
foreach (DataGridViewColumn col in Columns)
{
if (col.Visible)
width += col.Width;
}
if (ColumnHeadersVisible)
{
if (height == 0) height--;
height += ColumnHeadersHeight;
}
if (RowHeadersVisible) width += RowHeadersWidth;
if (BorderStyle == BorderStyle.FixedSingle)
{
width += 2;
height += 2;
}
else if (BorderStyle == BorderStyle.Fixed3D)
{
width += 5;
height += 5;
}
else
{
width += 1;
height += 1;
}
Size = new Size(width, height);
}
Lg, XXX
//Ein Edit muss noch dazu:
Das Property ist glaube ich im Designer nicht sichtbar. In dem Fall habe ich dann folgende Attribute noch angehängt:
bool _autoSize;
[Browsable(true),
Description("Steuert, ob die Größe des DataGridViews automatisch angepasst werden soll."),
Category("Verhalten")]
public override bool AutoSize
{
get { return _autoSize; }
set
{
_autoSize = value;
RefreshControlSize();
}
}
SqlLite würde mit der Datenmenge locker zurecht kommen aber wies mit mehreren Benutzern aussieht weiß ich allerdings nicht. Du hast in dem Fall eben eine Datei auf der Platte auf die direkt gelesen und geschrieben wird. -> Praktisch wenn man die Datenbank mit der Applikation gemeinsam ausliefert und nichts installieren will.
Ich habe nur Erfahrungen mit dem SQL Server. Ich würde dir den Empfehlern, weil er in der Express Variante ist er kostenlos und für deine genannten Anforderungen vollkommen ausreichend ist. Zusätzlich gibts mit dem Sql Server Management Studio ein tolles Tool zum Verwalten der Datenbank und die Anbindung zu .NET funktioniert auch reibungslos.
Jedes Datenbank Aktion steckt für sich selbst nochmals in einer Transaktion. D.h. mit oder ohne einer expliziten Transaktion, muss der Server Gewährleisten können, bei einem Fehlerfall die Daten wieder korrigieren zu können und dafür schreibt er halt alles in den Speicher/TempDb.
Ich weiß nicht ob es gezielte Lösungen dafür gibt aber du könntest deine Daten partiell einfügen: In einer Schleife zB jeweils 100k Datensätze einfügen. -> Braucht weniger temporäre Resourcen.
Ok, ich sehe gerade, dass dieses DeferRefresh in der ObservableCollection nur für Änderungen am Sort oder Filter gedacht sind. Nicht aber für Adds und Removes. Bei mir funktioniert es deshalb, weil ich meine "eigene" ObservableCollection implementiert habe in der ich während des Updates keine OnCollectionChanged Events mehr feuere und somit die View sich solange auch nicht mehr aktualisiert.
Hier meine Implementierung:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows.Data;
namespace XXXprod
{
public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged
{
public event NotifyCollectionChangedEventHandler CollectionChanged;
public ObservableCollection()
{
DefaultView = CollectionViewSource.GetDefaultView(this);
}
public ObservableCollection(IEnumerable<T> items)
: this()
{
AddRange(items);
}
public ICollectionView DefaultView { get; private set; }
private void OnCollectionCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (_deferringRefresh)
return;
NotifyCollectionChangedEventHandler handler = CollectionChanged;
if (handler != null)
handler(this, e);
}
private bool _deferringRefresh;
public IDisposable UpdateCollection()
{
_deferringRefresh = true;
return new DelegateDisposable(DefaultView.DeferRefresh(), () =>
{
_deferringRefresh = false;
RefreshCollectionView();
});
}
public void RefreshCollectionView()
{
DefaultView.Refresh();
}
public void Synchronize(IEnumerable<T> items)
{
using (UpdateCollection())
{
foreach (var removeResult in this.Except(items).ToArray())
Remove(removeResult);
foreach (var removeResult in items.Except(this).ToArray())
Add(removeResult);
}
}
public void AddRange(IEnumerable<T> items)
{
foreach (var item in items)
Add(item);
}
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
OnCollectionCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
protected override void RemoveItem(int index)
{
T item = base[index];
base.RemoveItem(index);
OnCollectionCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
}
protected override void SetItem(int index, T item)
{
T oldItem = base[index];
base.SetItem(index, item);
OnCollectionCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, oldItem, index));
}
protected override void ClearItems()
{
using (UpdateCollection())
{
T[] oldItems = this.ToArray();
foreach (T item in oldItems)
Remove(item);
}
}
}
public class DelegateDisposable : IDisposable
{
private readonly IDisposable _disposable;
private readonly Action _disposed;
public DelegateDisposable(IDisposable disposable, Action disposed)
{
_disposable = disposable;
_disposed = disposed;
}
public void Dispose()
{
if (_disposable != null)
_disposable.Dispose();
_disposed();
}
}
}