Laden...
M
Benutzerbeschreibung
Visual Studio 2012 C# !NET Framework 4 - FÜR WINDOWS XP UNTERSTÜTZUNG! WPF, DataBinding (einschichtig) über Entity Framework, SQL-Server 2000-2012

Forenbeiträge von m.grauber Ingesamt 343 Beiträge

17.03.2014 - 15:09 Uhr

Hallo Abt!

Ich habe den Code auch nur übernommen und die Umstellung auf DB-Context wird nun notwendig. Alles neu zu schreiben kommt nicht in Frage. Auch ich habe noch viele Defizite.

Daher bitte trotzdem versuchen zu Helfen! Danke 👍


MyMethode(System.Data.Entity.Core.Objects.DataClasses.EntityObject MyEObject){
}

Da werden z.B. Änderungen protokolliert. Übergeben wird ein Datensatz aus einer beliebigen Tabelle der Datenbank, z. B. kunde aus der Kunden-Tabelle oder lieferant aus der Lieferanten-Tabelle. Kann ich also Object verwenden oder gibt es ein spezielleres Objekt dafür?


kunden.PropertyChanged += new PropertyChangedEventHandler(_kunden_PropertyChanged); 

Davor ist "kunden" so definiert: public Kunden kunden = new Kunden();

Hier soll sofort Code ausgeführt werden, sobald sich etwas an irgend einem der Felder (z. B. Kundenname, Ort, Straße usw.) ändert. Bisher als EntityObject vor der Umstellung hat es einwandfrei geklappt und das PropertyChanged korrekt ausgelöst. Wie kann das nun ausgelöst werden, ohne den ganzen Code umzustellen?

Für die von mir geschriebene Refresh-Lösung gibt es keinen anderen Ansatz?

Nochmals vielen vielen Dank!!!

17.03.2014 - 14:12 Uhr

Hallo Abt!

Erstmal großen Dank für den Link zu den Framework-Tools! 👍 👍 👍 Und vielen Dank das man hier auch mit einem weniger großen Wissensstand Hilfe erfährt! 👍

Ich habe sie inzwischen installiert und den Code bereits begonnen umzustellen. Viele Sachen sind einfach nur an anderen Stellen untergebracht und können leicht angepasst werden.

Wo ich aber richtig Probleme habe ist folgendes:

Einer Methode kann ich irgend einen Datensatz übergeben. Bisher wurde der Parameter so übergeben:


MyDB.Kunden kunden = myEntities.Kunden.Where(...).FirstOrDefault();

MyMethode(System.Data.Entity.Core.Objects.DataClasses.EntityObject MyEObject){
}

Nach der Umstellung kommt natürlich beim Parameter "EntityObject" ein Fehler.
Darf ich hier stattdessen "Object MyEObject" angeben oder gibt es da etwas spezielleres, was benutzt werden sollte?

Außerdem gibt es keine Refresh-Methode mehr, bzw. sitzt sie wo anders:


myEntities.Refresh(StoreWins, kunden)

Jetzt könnte ich es scheinbar so lösen:


var context = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)myEntities).ObjectContext;
context.Refresh()

Dann nutze ich aber doch wieder über den ObjectContextAdapter indirekt den ObjectContext, den ich ja eigentlich vermeiden will. Kann ich das nicht anders und direkt lösen?

Und hier mein größtes Problem:


kunden.PropertyChanged += new PropertyChangedEventHandler(_kunden_PropertyChanged);

Warum gibt es kein PropertyChanged mehr? Hierzu habe ich nur sehr seltsame Lösungen gefunden, bei der die ..tt-Datei geändert werden muss. Das möchte ich natürlich unbedingt vermeiden! Gibt es dort etwas anderes?

Tausend Dank!

14.03.2014 - 17:16 Uhr

Hallo Abt!

public static ist ja nur die Methode, die mir die Verbindung zurückgibt. Dadurch kann ich sie einfach von überall aufrufen.

Die Verbindung selbst, die innerhalb der static-Methode erstellt wird ist ja dadurch nicht auch automatisch static. Es sollte daher also keine Probleme geben.

Sobald eine Verbindung nach der Benutzung später wieder geschlossen wird, räumt die GC ja trotzdem alles auf. Oder erzeugt das eine hängende Referenz?

CodeFirst oder EDMX

  • Was würdest Du empfehlen: Mit dem vorgeschlagenen Tool arbeiten oder besser gleich doch den CodeFirst Ansatz wählen?

  • Wenn ich den Db-Context+CodeFirst-Ansatz wählen würde, bekomme ich im gesamten Programm auch in gleicher Weise wie bisher (also bei ObjectContext+EDMX) Zugriff auf meine Daten und muss nur einige Namespaces und Typen ändern oder muss ich dann das komplette Verhalten meines Programms ändern?

Tausend Dank!

14.03.2014 - 16:40 Uhr

Danke für die schnelle Hilfe!

Bei Microsoft habe ich folgendes gefunden:

http://visualstudiogallery.msdn.microsoft.com/66612113-549c-4a9e-a14a-f629ceb3f89a

Dort wird aber geschrieben, dass man besser mit DB-Context arbeiten sollte und das Tool nur für bestehende Anwendungen nutzen sollte.

Das von Dir beschriebene Tool hat damit also nichts zu tun und ich kann damit zukünftig über DB-Context arbeiten? Stellt das Tool den Code automatisch um?

Und warum reicht es nicht das EF über Nuget zu ziehen? Ich bin dann doch zukünftig immer auf dieses Tool angewiesen? (Was ich auch nicht sein möchte. Evtl. wird es irgendwann einmal eingestellt?)

  • Ich möchte schon gleich auf DB-Context umsteigen.

  • Kann es sein, dass es irgend wann das Tool nicht mehr gibt und ich dann sowieso umstellen müsste?

Ich möchte später nicht noch mehr Arbeit haben und würde gerne die Umstellung probieren:

Ich habe z. B. einen Methode, die mit die Verbindung öffnet und die Verbindung als Rückgabewert zurückgibt:


public static MyEntities OeffneVerbindung(...)
{
   ...
   EntityConnection MyEntityConnection = null;
   MyEntityConnection.Open();
   ...
   MyEntities myEntities = new MyEntities(MyEntityConnection);
   ...
   return myEntities;

Leider findet er in der Zeile "public static MyEntities" nach der Umstellung zu DB-Context die "MyEntities" nicht mehr. Was muss ich dann dort angeben? Bisher habe ich danach über MyEntities.Tabelle auf die Daten zugreifen können. 🙁

Danke vielmals!

14.03.2014 - 16:05 Uhr

verwendetes Datenbanksystem: <SQL-Server 2012>

Hallo Experten!

Habe nun auf EF6 geupdatet und es wird höchste Zeit, auf Db-Context umzustellen. Ich nutze den Ansatz "DB first" und daher sollten mir auch in Zukunft aus den Tabellen der Code erstellt werden.

Ändere ich im Edmx-File die Strategie auf "Keine", bekomme ich ja in der Designer.cs nichts mehr angezeigt.

  • Wo muss ich dann meine Klassen definieren? 🤔

  • Bisher waren dort alle Klassen "Partial" definiert, was für mich auch wichtig ist, da ich sie an anderen Stellen noch erweitert habe. Kann ich sie beim Db-Context auch als partial definieren?

Gibt es irgend eine gute Anleitung dazu? 🙁

Danke vielmals

18.02.2014 - 17:10 Uhr

Hallo Abt!

Danke nochmals! 👍 Dann nutze ich erst einmal den integrierten Profiler.

Das .NET dann für ein einfaches Programm mal schnell 300 MB benötigt, wenn man WPF-Fenster einfach immer wieder öffnet und schließt kann ich trotzdem nicht ganz nachvollziehen.

Wenn die GC nur dann etwas cleared, wenn sie denkt, dass es gerade geht weil wenig "los" ist und es wahrscheinlich nicht mehr benötigt wird ist mir klar.

Aber ich dachte, der Vorteil der GC liegt darin, wenn ich ein Fenster mehrmals öffne und schließe die GC das erkennt und dann die alten Ressourcen erneut nutzt und so nicht mehr Speicher benötigt und die Aktion schneller durchführen kann.

Ich komme halt von der normalen "nicht-.NET" Entwicklung, wo die Programme um ein Vielfaches kleiner sind.

ALSO heißt das: Close() räumt tatsächlich alles weg und die GC kümmert sich sehr viel später darum. Ich werde mir dann keinen Kopf mehr machen.

Danke

18.02.2014 - 12:04 Uhr

Hallo Abt!

Danke für den Tipp mit dem Profiler. 👍 Da gehen allerdings die Preise bei 375 € los und enden bei 775 €. Gibt es erst einmal einen empfehlenswerten Freeware-Profiler?

Kann man sonst irgendwie die GC nach dem Schließen erzwingen? Close() müsste ja alles tatsächlich schließen. Hängende Referenzen dürfte es ja beim .NET nicht geben? Oder könnte ich diese erst einmal mit VS Bordmitteln lokalisieren?

Danke!

18.02.2014 - 10:19 Uhr

Hallo!

lasse ich mir im Taskmanager den Ressourcenverbrauch anzeigen wird beim Öffnen eines WPF-Fensters ca. 2-10 MB mehr Arbeitsspeicher verbraucht. Aber nach dem Schließen des Fensters mit Close() bleibt der Speicher weiter unverändert.

Nun gibt es ja den GC, der die Ressourcen dann wieder automatisch freigibt und dessen Verhalten man scheinbar nicht steuern kann.

Aber arbeitet man mit der Anwendung, werden aus 100 MB Anfangs-Speicherverbrauch schnell 300 MB. etc.

Gibt es noch nach Close ein Befehl, mit dem man wirklich Aufräumen kann. Wo kann ich den Ressourcenverbrauch genau überprüfen?

Danke

29.05.2013 - 14:11 Uhr

Weiß vielleicht jemand, nach welchem Begriff ich suchen könnte? Das ist ja wahrscheinlich schon eine Systemfarbe?

Es gibt schon einige Blautöne bei den Systemfarben aber alle weichen ab. Es muss also irgendwo anders hinterlegt sein.

23.05.2013 - 12:51 Uhr

Hallo!

Wenn unter Windows 8 eine WPF Textbox den Focus erhält, wird sie anders gefärbt. Ich habe bereits viele "SystemColors. ..." durchgesehen, aber diese exakte Farbe nicht gefunden. Wird da von Windows evtl. noch an der Opacity gespielt?

Wie komme ich in C# auf diese Brush?

Meintestbutton.Foreground=SystemColors.UnknownBrush;

(z.B. HighlightBrush oder ActiveBorderBrush ist es zumindest nicht)

Hat denn wirklich niemand eine Idee?

Danke

23.04.2013 - 16:54 Uhr

Hallo Florian,

vielen Dank.

Sagen wir wir haben die Tabelle1 und darin die Felder Checkwert1 bis Checkwert 10. Der aktuelle Datensatz ist bereits per Binding gebunden.

PropertyChanged ist auch bereits für den Datensatz abonniert. Es wirkt sich aber derzeit auf den gesamten Datensatz aus.

Im Fenster ist es notwendig, das Checkwert1 an mehreren verschiedenen Stellen geändert wird (abhängig von anderen Parametern). Aber nur wenn Checkwert1 durch manuelles Anklicken der Checkbox1 geändert wird, soll eine Messagebox geöffnet werden und weiterer Code abgearbeitet werden. Ich kann mich also nicht rein auf das Checkwert1-PropertyChange stützen. Daher am besten der Ansatz direkt über das Checkbox-Control.

Das muss doch möglich sein? Ich verstehe nicht, wieso Microsoft das so kompliziert gemacht hat?

23.04.2013 - 12:37 Uhr

Hallo!

Hat irgend jemand noch eine Idee? X(

Das muss man doch herausfinden können!?

22.04.2013 - 15:01 Uhr

Hallo Christian!

Inzwischen bin ich wieder da.

Das gleiche Problem habe ich jetzt mit einer Checkbox. Auch hier muss ich unterscheiden:

  1. Zweck:

Sobald die Checkbox gecheckt ist, soll IMMER ein bestimmter Text ausgegeben werden und verschiedenes am Layout geändert werden.

Das soll immer passieren (also wenn der Benutzer die Checkbox anklickt und auch wenn beim Laden der DataContext gesetzt wird)

  1. Zweck:

Klickt der User aktiv die Checkbox an, um sie umzustellen, soll noch eine zusätzliche Abfrage z. B. per MessageBox erfolgen. - Diese soll natürlich beim Laden nicht geöffnet werden, da ja nur der letzte Zustand wiederhergestellt werden soll und der User ja bereits diese Messagebox ggfls. angeklickt hatte.

Somit muss ich unterscheiden können, ob der User geklickt hat oder ob sich nur der DataContext geändert hat.

Wenn ich nun sehr viele Checkboxen und Comboboxen habe, muss es doch möglich sein, diese Unterscheidung zu treffen, ohne dass ich noch für jede Combobox und Checkbox ein manuelles IsManualFired einbaue?

(Irgendwie müsste man das ja im "sender" oder "e" sehen, ob es der DataContext ist oder ein Mausklick oder Return-Taste etc. - Ich habe aber alles verglichen - ohne den Unterschied zu finden.)

Danke

27.03.2013 - 12:56 Uhr

Hallo Xalir,

das ist bislang auch meine Lösung. Leider ist es nicht besonders elegant und wenn man später einmal mit mehreren Threads arbeitet, kann es sein, dass es zwischendurch umgeschalten wird.

Ich kenne es von anderen Programmiersprachen, dass es dort dafür sogar zwei unterschiedliche Events gibt.

Gibt es vielleicht noch Ideen? Hat das Microsoft vergessen?

Besten Dank!

27.03.2013 - 11:42 Uhr

Hallo,

wie löst ihr es, wenn ihr im ComboBox.SelectionChanged wissen wollt, ob das SelectionChanged ausgelöst wurde,

-> indem der Benutzer einen anderen Wert ausgewählt hat oder ob
-> es ausgelöst wurde, weil sich die Daten im Code geändert haben.

Sowohl in sender als auch e habe ich kein Unterschied feststellen können.

Besten Dank!

27.03.2013 - 11:38 Uhr

Hallo Xalir,

vielen Dank! Das ist wirklich Top! 👍 und wäre sicher die Lösung!!!

Leider habe ich wieder einmal einen Sonderfall:

Erstens ist x:Key im Style und nicht im darunter liegendem ControlTemplate definiert. (Im darunter liegendem ControlTemplate darf ich daher leider kein Key mehr vergeben).

Zweitens hatte ich x:Key="{x:Type ContextMenu}" gesetzt, damit es für alle ContextMenüs gilt. Sobald ich hier einen Name zuweise, müsste ich bei jedem ContextMenü im Programm den Style angeben.

Drittens habe ich einmal versucht, dann den Style trotzdem zu benennen und dann im Codebehind nach Style zu casten. Doch dieser Style hat leider kein .LoadContent() (oder etwas ähnliches) - Hier könnte man aber evtl. mit Trigger arbeiten.

Also ist nun zum Fortfahren derzeit das größte Problem, wie greife ich nun aus dem Codebehind auf den Style zu, wenn er mit x:Key="{x:Type ContextMenu}" bezeichnet ist? Ich habe bereits versucht eine Instanz des ContextMenüs zu bilden und dann mit .Style meinen Style auszulesen. Dieser ist aber immer null.

Besten Dank!

26.03.2013 - 12:47 Uhr

Hallo Erfinder des Rades,

vielen Dank für den Tipp! 👍 Ich habe inzwischen in die Richtung probiert, daß wird aber etwas aufwendiger. Da ich es bei allen ContextMenüs im Loaded ausführen möchte, gibt es evtl. noch einen anderen Weg:

Wie "abonniere" ich das Loaded des Standard-Context-Menüs (ohne es abzuleiten)?

Mit ContextMenu.Loaded += ... geht das ja nicht.

Mein Code sollte dann bei jedem erstellen eines neuen ContextMenüs abgearbeitet werden.

(Mein Template kann dann einfacher bleiben und muss das nicht berücksichtigen)

Wie klappt das dann? 🤔

Besten Dank!

25.03.2013 - 16:17 Uhr

Hallo,

in einem XAML-Template eines Contextmenüs, möchte ich dafür sorgen, dass beim Loaded aller Contextmenüs zukünftig ein Code Behind ausgeführt wird:


<Style x:Key="{x:Type ContextMenu}" TargetType="{x:Type ContextMenu}">
  <Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type ContextMenu}">
            <ControlTemplate.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                      <!-- Hier meinen Code Behind aufrufen: MyLoaded() -->
                </EventTrigger>
             </ControlTemplate.Triggers>
...

Nur was muss in dieser Zeile stehen? Und falls das nicht über das Template geht, welchen Code benötige ich in C#?

Es soll ein allgemeingültiges ContentMenu-Template bleiben.

Besten Dank!

25.03.2013 - 12:54 Uhr

Hallo Sarc,

vielen Dank für die schnelle Hilfe 👍

Diese Methode hatte ich auch schon in der Mache. Also gibt es keinen kürzeren Weg á la MainGrid() etc.

Ok. Dann wirds so gemacht.

Besten Dank!

25.03.2013 - 11:53 Uhr

Hallo,

ich möchte das äußerste Grid in einem WPF-Window ermitteln. Den Namen habe ich leider nicht, da er immer anders lauten kann. In jedem Fenster verwende ich aber ein solches Grid.

mein Fenster steht im Parameter "object sender".


Window MeinFenster = (Window)sender;

VS gibt ja bereits in jedem Grid ein Fenster vor. Ich hoffe nun, dass ich irgendwie über MeinFenster auf das erste (äußerste) Grid komme. Nur wie?

  1. Muss ich wahrscheinlich statt nach Window zu casten ein Interface benutzen?

  2. Wie muss eine Methode LiefereAeusserstesGrid() lauten? - Ich habe da überhaupt keinen Ansatz. Ich vermute es muss eine Zeitaufwändige Sache über FindVisualChildren sein? Doch woher weiss ich, welches Grid das äußerste ist?

Danke für Eure Mühe!

25.03.2013 - 11:42 Uhr

Hallo,

bin nicht weitergekommen und habe es nun ohne Binding gemacht.

Danke trotzdem

22.03.2013 - 15:15 Uhr

Hallo,

in einem anderen Fenster muss ich mit ElementName auf mein Hauptfenster referenzieren. Er findet aber MeineForm nicht, da sie nur im Hauptfenster mit Name="MeineForm" definiert ist.

22.03.2013 - 14:45 Uhr

Hallo,

ich habe im Hauptfenster (was immer geöffnet ist) eine DependencyProperty. Mir ist klar, wie ich im XAML im gleichen Fenster auf diese DependencyProperty zugreife.

Nur wie kann ich im XAML Code eines anderen Fensters auf die DependencyProperty des Hauptfensters zugreifen (oder wo muss ich die DP hinpacken, dass ich von anderen Forms darauf zugreifen kann?


...={Binding ElementName=MeineForm, Path=MeineProperty}

Es sollte halt schon ein XAML Einzeiler sein.

13.03.2013 - 15:51 Uhr

Hallo Console32!

Dann nochmals vielen Dank! 👍 Dann werde ich so arbeiten.

Winterliche 🙂 Grüße

13.03.2013 - 11:58 Uhr

Hallo Console 32,

Vielen Dank! Durch das Binding gibt es das Objekt. Natürlich kann ich das Casten und erhalte dann Zugriff auf den Namen, der auch angezeigt wird. Doch muss ich immer so vorgehen? Das ist doch schon eine seltsame Verhaltensweise zwischen SelectionChanged und dem Inhalt von .Text?

Aber wenn es so sein muss, werde ich das natürlich wieder Casten und es passt. Ich gehe halt lieber den direkten und weniger rechenintensiven Weg.

Beste Grüße!

13.03.2013 - 10:45 Uhr

Hallo,

In einer einfachen WPF Combobox greife ich im SelectionChanged auf den Text der Combobox zu. Dort steht aber immer noch der alte Text drinnen:


<Combobox .... SelectionChanged="Combobox_SelectionChanged_1"


private void Combobox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    MessageBox.Show(Combobox.Text);
}

  • Warum wird dort noch nicht bereits der neue Text angezeigt? (Die Methode heißt doch "SelectionChanged" und nicht "BeforeSelectionChanged"?

  • Wie kann ich bereits auf einfachste und schnelle Weise den neuen Text anzeigen? Nutzt ihr ein anderes Event o. a.? (Ich rufe im SelectionChanged eine weitere allgemeingültige Methode auf; daher bitte nicht e.AddedItems[0]... vorschlagen. Ich muss von dieser externen Methode auf "Combobox.Text" zugreifen, da es dort kein e gibt).

  • Warum schreibt VS 2012 bei jeder automatisch generierten Methode "_1" ans Ende? - Unter VS 2010 war das noch nicht so. Ändert ihr das jedes Mal?

Besten Dank!

05.03.2013 - 15:38 Uhr

Hallo kleiner Tomy,

Auch Dir lieben Dank! Leider nicht. Dort wird schon richtig Instanziiert:


Objekt oob = new Objekt();
return oob

aber sobald es aus der Methode raus geht, sage ich folgendes:


Mein_Fenster.Mein_Interface.Obj = Erstelle_Mein_Obj();

An dieser Stelle vermute ich das Problem.

Da es Mein_Fenster.Mein_Interface.Obj ja einfach zugewiesen wird, statt eine neue Instanz zuzuweisen. Ich vermute daher, dass irgentetwas durch die Schnittstelle anders läuft und durch die Schnittstelle evtl. irgend ein "vorheriger" Wert (der in einem ganz anderen Fenster gesetzt wird) überschrieben wird.

Aber wenn das bei Schnittstellen nicht passieren kann; mit was ich eigentlich rechne, dann teilt es mir bitte mit. Es muss dann noch etwas anderes sein.

Bin noch immer nicht weiter damit.

05.03.2013 - 13:36 Uhr

Vielen Dank für die Hilfe!

Ich muss mich leider korrigieren und etwas ausholen:

Im Moment greife ich auf die Member aus dem Interface so zu:


public interface IMein_Interface
{
  Meine_Klasse meine_Klasse { get; set; }
}

public class Meine_Klasse
{
	public string Obj { get; set; }
}

(In Meine_Klasse befinden sich noch weitere Member.)

In der Form wird das Interface mit :IMeine_Klasse verwendet und mit...


public Meine_Klasse {get;set;}

...verwendet. Es wird also schon doch korrekt implementiert. Ich bin nur durch die "Unterklasse" durcheinander gekommen.

Dadurch erhöht sich die Übersichtlichkeit und ich kann mehrere Member in verschiedene "Bereiche" (d.h. Interfaces) gliedern, statt das dann auf alles nur mit this.Obj bzw. this.Obj2 zugegriffen wird.

==> Wie verhält es sich nun mit diesen "Unter-Membern" also z.B. Obj? Muss ich in der Form nun nicht nur das Interface definieren, sondern auch noch das Obj aus der Klasse des Interfaces?


Meine_Klasse.Obj=new Meine_Klasse();

Das mache ich bisher nur dann wenn ich diese mit abweichenden Werten benötige, was eine Menge Arbeit spart. Besonders, wenn ich neue Member benötige muss nichts nachgetragen werden.

Das Problem ist nun im Ansatz klar: Im Interface verweise ich auf eine Klasse, die ich aber nicht instanziiere. Wie kann ich das trotzdem nutzen? Und wurden meine Probleme dadurch verursacht?

Besten Dank!

05.03.2013 - 11:59 Uhr

Hallo Inflames!

Danke sehr für die schnelle Rückmeldung!

Ich habe es noch ergänzt.

Da das Interface in mehreren Forms verwendet wird, "haftet" scheinbar durch die letzte Zuweisung noch mein Objekt der zuletzt geöffneten Form drin und wird scheinbar überschrieben, da ich ja direkt einen neuen Wert mit = zuweise.

Mit der obersten Zeile wird das definitiv verhindert. Nur möchte ich diese Zeile nicht bei jedem öffnen des Fensters schreiben.

Ich habe es inzwischen mit einem einfacheren String Objekt getestet. Dort beeinflusst es sich nicht gegenseitig.

Ich benötige irgendwie eine Instanz.

**
Oder kann ich das Objekt Obj evtl. direkt im eigenen Objekt-Konstruktor von Obj instanziieren?**

Besten Dank

05.03.2013 - 11:32 Uhr

Hallo,

In einem Interface "Mein_Interface" ist definiert:


public string Obj { get; set; }

Dieses Interface wird mit einer Form verwendet:


public partial class Mein_Fenster : Mein_Interface

ich sage nun im Load des Forms:


Mein_Fenster.Mein_Interface.Obj = new Obj();
Mein_Fenster.Mein_Interface.Obj = Erstelle_Mein_Obj();

**
Wie kann ich im Interface die Instanz erzeugen, damit ich mir die oberste Zeile im Load des Forms sparen kann: Mein_Fenster.Mein_Interface.Obj = new Obj();**

(Jedes einzelne Fenster soll mit einer unterschiedlichen Instanz von Obj arbeiten, also je Fenster unterschiedliche Werte enthalten, die sich nicht gegenseitig beeinflussen.

Es handelt sich in Wirklichkeit nicht um einen string, sondern ein komplexeres Objekt (Referenztyp!), welches scheinbar durch das nachfolgend geöffnete Fenster überschrieben wird, wenn die derzeit oberste Zeile im Load fehlt.)

Einfach in den Konstruktor des Interfaces hineinschreiben wird ignoriert (das Interface ist ja nur der Bauplan). Das Init-des Interfaces zu abonnieren, wird leider auch ignoriert.

Es muss auch weiterhin ein Interface bleiben.

Besten Dank!

31.01.2013 - 15:22 Uhr

Hallo Christian,

vielen Dank für Deine Mühe. 👍

Wahrscheinlich bin ich völlig blöd 🤔, aber wohin soll ich das setzen❔

public override void OnApplyTemplate()
...

  1. In allen WPF-Forms nutze ich die normalen WPF-ComboBox (ohne Ableitung!)

  2. Alle WPF-Comboboxen werden durch das Template in meiner App.xaml beeinflusst:

<ControlTemplate x:Key="ComboBox" TargetType="{x:Type ComboBox}">
...

  1. Ich möchte das SelectionChanged meines Templates abonieren - Damit soll mein gewünschter Code bei jedem SelectionChanged jeder Combobox ausgeführt werden - ohne dass dann nochmals je benutzter Combobox separaten Code bemühe.

Ich müsste dann beim Programmstart folgende Zeilen ausführen:

System.Windows.Controls.ComboBox combo = new System.Windows.Controls.ComboBox();
combo.SelectionChanged += combo_SelectionChanged;

dann könnte ich genau definieren, welcher Code ausgeführt werden soll. Leider wirkt sich dieser Code nur auf diese einzelne Combobox aus.

OnApplyTemplate könnte ich auch nur ausführen, wenn ich vorher eine Instanz einer Combobox habe. ** Ich habe aber nur ein Template: **


<ControlTemplate x:Key="ComboBox" TargetType="{x:Type ComboBox}">

Nun habe ich mir auch schon System.Windows.FrameworkTemplate angesehen, komme aber nach Tagen leider noch immer nicht weiter.

Ich habe auch bereits versucht dem Template mit x:Name="" ein Namen zu geben und darauf zuzugreifen. Klappt leider auch nicht.

Bitte nochmals um Hilfe! Danke sehr!

31.01.2013 - 12:29 Uhr

Hallo Christian,

ich habe mich sicherlich etwas falsch ausgedrückt. Ich habe auch durch sehr langes Suchen nichts gefunden, da ich auch nicht weiss, nach welchem Begriff ich suchen soll.

Mit dem EventTrigger wird beim SelectionChanged etwas ausgeführt. Das ist ok so und läuft.


<ControlTemplate x:Key="ComboBox" TargetType="{x:Type ComboBox}">
  <ControlTemplate.Triggers>
     <EventTrigger RoutedEvent="SelectionChanged">
       ...
     </EventTrigger>
  </ControlTemplate.Triggers>
</ControlTemplate> 

**
Ich möchte in meinem XAML-Code dieses SelectionChanged zusätzlich abonieren. Im Code Behind eines normalen Controls würde ich es so machen:**


Combo.SelectionChanged += Combo_SelectionChanged;
void Combo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
  ...
}

**
Da ich aber hier in einem Template bin, geht das so nicht. 🤔**

Wie ist dafür die XAML-Syntax?


<ControlTemplate x:Key="ComboBox" TargetType="{x:Type ComboBox}">
  <ControlTemplate.Triggers>
     <EventTrigger RoutedEvent="SelectionChanged" += "{x:Static local:ComboTemplate_SelectionChanged}">
       ...
     </EventTrigger>
  </ControlTemplate.Triggers>
</ControlTemplate> 

Der Code soll wirklich für alle Controls ausgeführt werden, die dieses Template benutzen.

Vielen Dank!

31.01.2013 - 09:21 Uhr

Hallo,

hat wirklich niemand eine Antwort? X(

Vielen Dank

29.01.2013 - 16:48 Uhr

Hallo,

Für ein Control habe ich ein Template. Wie muss die XAML-Zeile aussehen, dass ich z. B. beim SelectionChanged Code-Behind ausführen kann?


<ControlTemplate x:Key="ComboBox" TargetType="{x:Type ComboBox}">
  <ControlTemplate.Triggers>
     <EventTrigger RoutedEvent="SelectionChanged">
       RunMyCSharpMethod()
     </EventTrigger>
  </ControlTemplate.Triggers>
</ControlTemplate>

Dieser Code soll bei jedem SelectionChanged jeder ComboBox ausgeführt werden und zwar bevor noch evtl. weiterer an das SelectionChanged angebundene Code ausgeführt wird.

Danke vielmals!

24.01.2013 - 16:27 Uhr

Hallo Christian,

vollkommen richtig! Es läuft nun. Ich hatte wirklich Tomaten auf den Augen 8)

Nun ist mir auch die Weiterleitung klar geworden.

Tausend Dank nochmals! 👍

Grüße
Michael

24.01.2013 - 14:50 Uhr

Hallo Christian,

vielen Dank für die Hilfe! Darüber, dass das ein Control in einem anderen Control ist, habe ich auch schon nachgedacht. Ich dachte bisher aber immer "TemplatedParent" bezieht sich auf das gesamte ("äußere") Template.

Aber das "TemplatedParent" bezieht sich also nicht auf das gesamte ("äußere") angewandte Template sondern nur auf das jeweils übergeordnete?

Wenn es so ist, habe ich die von Dir beschriebene Zeile nochmals eingebaut:

Es kommt keine Fehlermeldung (es wird zumindest nichts angezeigt) aber ändern tut sich auch nichts. Ich leite so diesen Wert über die Combobox an den Toggle Button weiter?


<Style x:Key="{x:Type MyComboBox}" TargetType="{x:Type MyComboBox}">
...
<Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ComboBox}">
                        <Grid>
                           ...
<ToggleButton x:Name="ToggleButton" Template="{StaticResource ComboBoxToggleButton}" Grid.Column="2" Focusable="false" ClickMode="Press"
                                          IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" 
BorderThickness="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness}"/> 

Vielleicht muss ich noch etwas anderes beachten?
(Ich habs getestet: Die Weiterleitung an die Combobox klappt, die erneute Weiterleitung an den ToggleButton wird ignoriert)

Danke!

24.01.2013 - 13:42 Uhr

Hallo,

in <Application.Resources> habe ich u. a. folgendes Template für eine ComboBox erstellt:

Hier das Template für die eigentliche ComboBox:


<Style x:Key="{x:Type MyComboBox}" TargetType="{x:Type MyComboBox}">
...
<Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ComboBox}">
                        <Grid>
                           ...
<ToggleButton x:Name="ToggleButton" Template="{StaticResource ComboBoxToggleButton}" Grid.Column="2" Focusable="false" ClickMode="Press"
                                          IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>

Hier das Template für den von der ComboBox benötigten ToggleButton:


<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="{x:Type ToggleButton}">
<Grid>
  ....
  <Border x:Name="Border" BorderThickness="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness}" 
   ...

Wenn ich nun eine ComboBox auf ein Fenster setze, klappt alles.

Wenn ich aber im Fenster für eine bestimmte Combobox die BorderThickness="5" setze, wird dies ignoriert. Ich möchte, dass die im Fenster bei der ComboBox eigegebene BorderThickness in das Template übergeben wird. Daher ist oben auch die Zeile "BorderThickness="{Binding RelativeSource..." drin.

Wie muss diese Zeile korrigiert werden?

Danke.

16.08.2012 - 13:38 Uhr

Hallo xxxProd und Christian,

also dieses Control vom alten Kollegen ist wirklich des Wahnsinns. - Ich werde es nun selbst "nachbauen" und daher benötige ich nun keine Lösung mehr. Dann kann ich es an dieser Stelle auch anders lösen.

Vielen Dank nochmals.

16.08.2012 - 12:55 Uhr

Hallo Christian,

auch Dir vielen Dank! 👍 Die Zeilen


<UserControl.Resources>
        <DataTemplate x:Key="MyTemplate">
            <local:MyUserControl/>
... 

"führen" in einer bestimmten Situation dazu, dass MyUserControl.xaml geladen wird.

Wie kann ich stattdessen MyMethode "laden", die sich im Codebehind befindet? - ** Theoretisch möchte ich nur diese eine Zeile ändern. **

Aufgrund von xxxprod versuche ich es gerade mit DataTemplate.Triggers, bekomme es aber nicht hin.

Das UserControl ist leider geschlossen und der Kollege, der das programmiert hat, ist nicht mehr da. Auf jeden Fall wird immer dieses MyUserControl ausgeführt und das klappt derzeit ja auch. - Ich möchte nur eine andere Methode angeben, statt einem UserControl zu öffnen.

Ist vielleicht der Grund, warum der Kollege das damals so gemacht hat, dass es anders nicht geht? X( X(

Also mir ist klar, dass ich aus dem XAML-Code nicht auf Public oder Static Methoden zugreifen kann. Jedoch auf DependencyProperties. Leider klappt auch das nicht:


<UserControl.Resources>
        <DataTemplate x:Key="MyTemplate">
            <local:MyDependencyProperty/>
... 

(dabei ist MyDependencyProperty im aktuellen UserControl eine korrekt erstellte DependencyProperty. Dort könnte ich dann zumindest etwas abonieren).

16.08.2012 - 11:30 Uhr

Hallo xxxprod,

das ist ein UserControl welches bei einer bestimmten Aktion dieses Template "auslöst". - Bitte nicht über meine seltsame Beschreibung lachen 🙂

Dabei wird MyUserControl erstellt. - Ich möchte aber statt der Zeile


   <local:MyUserControl/>

dass nicht das MyUserControl.xaml erstellt wird, sondern eine Methode im CodeBehind des gleichen Controls aufgerufen wird:


   <local:MyMethode/>             // geht natürlich nicht

Wie lautet die korrekte Syntax, um auf meine Methode zu verweisen?

Danke!

16.08.2012 - 10:16 Uhr

Hallo,

im XAML habe ich folgenden Ressource-Code:


<UserControl.Resources>
        <DataTemplate x:Key="MyTemplate">
            <local:MyUserControl/>
...

So wird beim Aufruf zwar von MyUserControl.xaml (einem Usercontrol) eine neue Instanz gebildet und steht zur Verfügung.

**
Ich möchte aber an dieser Stelle stattdessen nur eine im CodeBehind definierte Methode ausführen. - Auf den DataContext möchte ich aber in der Methode trotzdem zugreifen; er muss also mit "übergeben" werden. Wie geht das?**

Danke!

16.08.2012 - 09:47 Uhr

Hallo Thorxx,

Danke für Deine schnelle Hilfe! - Ja, Du hast die englische Version mit der englischen Fehlermeldung - ich "leider" die Deutsche. Ich hatte schon ausführlich gesucht, aber auch keine richtigen Lösungen gefunden.

Da dies viele für einen Bug halten, werde dies im neuen VS2012 testen. Falls dann behoben ist es am besten, da ich dann nichts umbiegen muss.

Danke nochmals! 👍

10.08.2012 - 13:21 Uhr

Hallo,

ich habe mir ein eigenes TabItem abgeleitet. Derzeit ist noch kein Unterschied zum normalen TabItem ausprogrammiert.

Wenn ich in mein TabControl nun statt dem normalen TabItem mein eigenes TabItem setze, bekomme ich folgende Fehlermeldung:

Fehlermeldung:
Der Wert "Grid1" des Name-Attributs kann für das Element "Grid" nicht festgelegt werden. "Grid" befindet sich im Bereich des Elements "MyTabItem", für das bereits ein Name registriert wurde, als es in einem anderen Bereich definiert wurde.

**
Hinweis: Dem TabItem wurde mit Name="MyTabItem1" ein Name zugewiesen und dem Grid innerhalb des Tabitems wurde auch ein Name="Grid1" zugewiesen.**

Warum kann ich dies beim Standard TabItem problemlos machen und bei meinem abgeleiteten TabItem nicht? - Und wie kann ich das umgehen? (Ableitung ist korrekt mit public partial class MyTabItem : TabItem erfolgt)

Vielen Dank!

06.08.2012 - 14:35 Uhr

Hallo,

in einem WPF-Datagrid, was an eine Observable Collection (mit Feldern Datum und DatumFormat) gebunden ist, versuche ich folgendes:


<DataGridTextColumn Binding="{Binding Path=Datum, StringFormat={Binding Path=DatumFormat}}" />

Habe es inzwischen allein herausgefunden. Das klappt so nicht. Ich habe nun doch alles als Text ausgegeben und das ist so ok.

24.01.2012 - 14:54 Uhr

Die Entitäten haben trotzdem einen EntityState, mit dem gearbeitet werden kann. Das ist natürlich nicht so komfortabel wie die STE´s.

24.01.2012 - 14:11 Uhr

Hallo Abt,

ja, mit dem MVVM Pattern werde ich mich in meiner nächsten Anwendung ganz bestimmt befassen. - Versprochen!

Die Self-Tracking Entities wurden erst in einer späteren Version eingeführt; daher arbeite ich nicht damit. Trotzdem ein sehr interessanter Artikel!

Wenn Du immer noch der Meinung bist, das sie die Aufgabe von MS, dann hast Du allem Anschein noch nie wirklich damit intensiv gearbeitet bzw. dich mit der Situation und den Folgen intensiv auseinander gesetzt.

---> Ja, das ist sicher so. Jedoch muss ich beim SQL-Server auch nicht abfangen, ob gleichzeitig noch andere Zugriffe stattfinden, sondern alles wird von ihm selbst in Queues abgearbeitet. Aber das ist nur meine Ansicht und hängt sicher mit der inneren Funktionsweise zusammen.

Also werde ich vorerst lock verwenden!

Vielen Dank nochmals! 👍

24.01.2012 - 12:42 Uhr

Hallo herbievore,

auch Dir vielen Dank für den Tipp! 👍

Ich habe mir den Beitrag sehr aufmerksam durchgelesen. Das ist sicher eine 1a Lösung, würde allerdings eine starke Umgestaltung meines Codes erfordern. Ich hoffe, ich habe es halbwegs richtig verstanden:

Zudem müsste dann wirklich jeden Lese und Schreibvorgang als eigenen Thread ausformulieren und die Parameterübergabe bzw. Rückgabe der Werte sind aufwendiger. Und sowohl nach dem Auslesen oder dem Speichern müssen weitere Schritte durchgeführt werden, die bei Ende des Threads aufgerufen werden müssen.

Ich werde daher wahrscheinlich doch mit lock arbeiten, da dies für mich derzeit noch wesentlich einfacher ist. Lock kümmert sich dabei selbstständig um das Warten und führt einen Block nach dem nächsten aus und arbeitet für mich somit ähnlich einer Queue (Egal, ob das Lock aus dem Hauptthread oder anderen Threads erfolgt). Diesen einfacheren Weg werde ich ersteinmal wählen, da ich dieses Problem an sehr wenigen Stellen habe. Aber auch hier, muss ich alle Lese- und Schreibaktionen, bei denen es nötig ist, per lock kapseln.

Grüße

24.01.2012 - 12:12 Uhr

Hallo Abt,

es ist eine WPF-Anwendung. Nein, ich vermische hier eigentlich nichts. Wenn ich eine Entität (z. B. Kunden) lade, dann verändere und später die Änderungen wieder abspeichere, muss ich dafür die gleiche Dataconnection benutzen. Sonst funktioniert die "Änderungsmechanik" vom Entity Framework nicht.

Ich habe es daher so aufgebaut, dass ich dafür die gleiche Connection benutze. Bei anderen Entitäten (z. B. Artikel) nutze ich aber eine andere Connection.

Ich sehe mir auch einmal die SyncQueue von herbievore an.

Grüße

23.01.2012 - 16:30 Uhr

Hallo Abt,

nein, ich fahre keine Formel 1 Rennen. 8) Manchmal muss aber bei Updates (wg. der Änderungsverfolgung) der gleiche Kontext genutzt werden, sonst klappt es nicht. Ansonsten versuche ich so etwas natürlich zu vermeiden.

Trotzdem bin ich der Meinung, dass Microsoft so etwas abfangen sollte, indem es die Zugriffe zumindest in eine Queue schreibt und dann nacheinander abarbeitet. Ich möchte mich als Entwickler eigentlich nicht mit diesen "Hintergrund-Dingen" beschäftigen müssen.

Vielleicht fällt jemanden ja noch etwas ein. 🤔

Grüße

23.01.2012 - 15:40 Uhr

Hallo Abt,

vielen Dank für die schnelle Antwort! 👍

Das pauschale "Ja" zu allen Lock-Fragen heißt also folgendes❔

  • Die Exception kann auch auftreten, wenn man zur gleichen Zeit mit verschieden (SQL-Server)-Tabellen bzw. Entitäten arbeitet (egal ob lesend, schreibend oder gemischt) - also auch wenn die Zugriffe miteinander nichts zu tun haben.

  • Wenn .NET einen Lock-Block gerade abarbeitet, laufen der Haupttask und die weiteren Hintergrund-Tasks so lange "parallel" weiter, bis das gleiche Objekt gelockt wird.

  • Arbeitet .NET gerade einen Lock-Block ab und wird ein zweiter und ggf. noch ein dritter Lock-Block mit dem gleichen Objekt in dieser Zeit aufgerufen, stoppt .NET nur am zweiten und dritten Lock-Block solange, bis der erste Lock-Block fertig ist und setzt dann die Arbeit im zweiten Lock-Block fort und nach dessen Beendigung dann den dritten. .NET reiht also die Lock-Blöcke gleicher Objekte in eine Queue.

  • Ich muss also jeden parallel möglichen Zugriff über meinen Datenkontext in einem Lock-Block auf das gleiche Objekt kapseln um Fehler zu vermeiden?

Du sprichst von einer Doku des Entity Frameworks. Kannst Du bitte einen Link über das so umfangreiches Dokument posten? So etwas suche ich bereits länger. Oder meinst Du die MSDN?

Evtl. weiß jemand etwas, ob Microsoft im neuen Visual Studio beim Entity-Framework inzwischen die Threadsicherheit implementiert hat?

Gibt es außer dem Lock vielleicht noch andere Möglichkeiten, um eine Parallelität im Entity Framework sicherzustellen?

Nochmals vielen Dank!