Laden...

Forenbeiträge von Quaneu Ingesamt 692 Beiträge

28.11.2012 - 13:53 Uhr

So jetzt bin ich einen Schritt weiter 😃

Wenn ich im DataGrid z.B. erst Zeile 2 selektiere und dann wieder Zeile 1 und nun kontakt.Name = "Hans" ausführe updatet das DataGrid.
D.h. Wenn das DataGrid initialisiert wird und ich die vorselektierte Zeile markiere (Zeile 1) und auf dieser kontakt.Name = "Hans" ausführe, updatet das DataGrid nicht, wenn ich eine andere Zeile als die vorselektierte Zeile selektiere funktioniert es.

28.11.2012 - 13:31 Uhr

Ehrlich gesagt weiß ich nicht was ich noch zeigen soll.
Wenn Du gerne eine bestimmte Stelle sehen möchtest, dann frag einfach und ich zeige sie Dir.

Schöne Grüße
Quaneu

28.11.2012 - 13:19 Uhr

Hallo ErfinderDesRades,

im Grunde mach im "hier nicht gezeigten Code" nicht sehr viel mehr.
Ich ändere nur den Name des Kontakts. Wenn ich DataGrid.Items.Refresh() aufrufe sehe ich die geänderten Daten. Doch dies gefällt mir ganz und gar nicht.

Schöne Grüße
Quanue

28.11.2012 - 10:24 Uhr

Hallo zusammen,

ich suche schon seid 3 Stunden nach dem Fehler, aber ich finde ihn leider nicht...
Ich habe Window indem ich ein eigenes UserControl (KontakteUserControl) verwende, indem ein DataGrid ist.

Window:


<controls:KontakteUserControl />

KontakteUserControl:


<DataGrid ItemsSource="{Binding Kontakte, Mode=OneWay}">
	<DataGrid.Columns>
		<DataGridTextColumn Header="Name"
				Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="*" />
	</DataGrid.Columns>
</DataGrid>

MyList ist eine ObservableCollection<Kontakt>. Kontakt besitzt das Property


public String Name
{
	get { return this._name; }
	set
	{
		this._name = value;
		OnPropertyChanged("Name");
	}
}

Wenn ich nun bei einem Kontakt aus der ObservableCollection den Namen ändere (kontakt.Name = "Hans") updatet sich das DataGrid und zeigt in der betroffenen Zeile z.B. nach wie vor Peter an. Wenn ich dann aber z.B. die Zeilen sortiere, steht Hans in der Zeile.

Ich weiß nicht was ich falsch mache...

Ich hoffe mir kann jemand auf die Sprünge helfen.

Schöne Grüße
Quaneu

19.11.2012 - 10:26 Uhr

Hallo Rabban,

leider nicht, das TabControl sollte nur als Beispiel dienen.

Schöne Grüße
Quaneu

19.11.2012 - 09:11 Uhr

Hallo herbivore,

vielen Dank für deine schnelle Hilfe.

Doch leider hat auch dieses Custom ContainerControl das selbe Problem wie die anderen.

Wenn ich z.B. die GroupBox in das Custom ContainerControl ziehe kann ich diese nur an dem Custom ContainerControl selbst "andocken" (mit andocken meine ich, dass wenn ich die GroupBox an den Rand ziehe das Control bei einer bestimmten Entfernung einrastet und im Designer ist eine dünne Linie zu sehen).
Des Weiteren kann ich die GroupBox überall im Custom ContainerControl platzieren und nicht nur auf den dafür vorgesehenen Platz.

Kann man sich irgendwo den SourceCode für das TabControl und TabPages für Windows Forms anschauen? Da könnte ich es mir ja abschauen 😃.

Schöne Grüße
Quaneu

16.11.2012 - 20:49 Uhr

Hallo zusammen,

ich will ein UserControl implementieren, dass ich im Designer wie eine Art TabControl verwenden kann. Dazu bin ich über den Artikel
Wie Sie ein UserControl-Objekt fungiert als eine Steuerelement-Container-Entwurfszeit mithilfe von Visual C#
und
Designing Nested Controls
gestoplert.

Doch leider komme ich hier nicht so ganz weiter. Wobei mit Hilfe des letzten Artikels schaffe ich es, dasss mein UserControl als Container fungiert. Wobei leider immer nur das ganze Control als Container dient und nicht wie im Beispiel die WorkingArea. Man kann z.B. auch nicht an den Rändern der WorkingArea "andocken".

Daher meine Frage kennt jemand noch andere Artikel diesbezüglich bzw. kann mir wer anders weiterhelfen?

Schöne Grüße
Quaneu

15.11.2012 - 16:50 Uhr

Danke für eure Hilfe.
Werde wohl mein Farbschema ändern... hätte ich das mal früher gewusst 😃

Schöne Grüße
Quaneu

15.11.2012 - 13:55 Uhr

Ich kann Dir leider nur sagen das der default Cursor (Arrow) weiß bleibt.

15.11.2012 - 13:09 Uhr

Hast Du auch im System unter "Eigenschaften von Maus" den Haken "Zulassen, dass Mauszeiger durch Designs geändert werden" drin?

Ja ist drinnen.

FYI: Bei mir sehe ich dann gar nicht mehr (also den Teil des Cursors, der sich im Bereich der Textbox befindet). Das sieht dann so aus, als ob der Textbox-Hintergrund direkt über den Cursor gezeichnet wird.

Bei mir ist das Verhalten genau so. Wenn ich dann ganz genau hinschaue sehe ich noch ganz ganz feine Umrisse (aber dann sitze ich 2cm vorm Bildschirm).

15.11.2012 - 12:51 Uhr

Hallo zusammen,

ich habe eine TextBox mit der Hintergrundfarbe 130; 129; 136 (dunkles grau). Wenn ich nun den Cursor (IBeam) über diese bewege, bekommt dieser eine sehr ähnliche Farbe und ist somit (fast) nicht mehr sichtbar.
Wieso bleibt der Cursor nicht schwarz? Beheben kann man dies wahrscheinlich nur mit MouseOver und so... dies würde mir nicht wirklich gefallen.

Daher meine Frage: Kann man dieses Problem auch anders lösen?

Viele Grüße
Quaneu

26.10.2012 - 13:24 Uhr

UPDATE:

Wenn ich

Application.EnableVisualStyles();

vor

Application.Run();

entferne geht es unter Windows XP auch. Doch habe ich gelesen, das man für Windows XP Application.EnableVisualStyles() aufrufen sollte. Nun befinde ich mich in einer Zwickmühle...

Schöne Grüße
Quaneu

26.10.2012 - 11:50 Uhr

Hallo herbivore,

welche Auflösungen passenden denn und welche nicht?

Geht: (1856 x 1238) oder (2560 x 1600)
Geht nicht: (1607 x 1090) oder (1024 x 768)

Nur die Anzahl der Bildpunkte oder auch die DPI-Einstellungen?

Nur die Anzahl der Bildpunkte.

Ändert sich nur die Fenstergröße des VM-Fensters oder auch die aktuelle Auflösung des Monitors?

Die Auflösung des Fensters.

Dieses Problem taucht nur unter Windows XP auf unter Windows 7 gibt es bei den Auflösungen (1607 x 1090) oder (1024 x 768) auch kein Problem.

26.10.2012 - 09:14 Uhr

Hallo zusammen,

ich habe ein ganz komisches Verhalten, das ich mir nicht erklären kann...
Ich benutze einen TreeView der eine ImageList besitzt, um den TreeNodes Icons zu verpassen. Dies klappt auch wunderbar, d.h. sie werden immer angezeigt.

Wenn ich das Programm nun in einer VM benutzt und ich dort die Fenstergröße und dadurch die Auflösung ändere sind die Icons verschwunden. Dies passiert nicht während das Programm läuft sondern nur wenn ich es starte und die Auflösung nicht "passt".

Ich hab nur folgendes gefunden:
Msdn: TreeView.ImageList-Eigenschaft

Aufgrund eines Fehlers in Microsoft .NET Framework, Version 1.1, werden Bilder in TreeView-Knoten nicht angezeigt, wenn die Anwendung Application.EnableVisualStyles aufruft. Rufen Sie zum Umgehen dieses Problems Application.DoEvents in der Main-Methode unmittelbar nach dem Aufrufen von EnableVisualStyles auf. Dieser Fehler wird in .NET Framework 2.0 behoben.

Da ich aber Framework 3.5 benutzt sollte dies bei mir nicht zutreffen...

Weiß vielleicht jemand woran dies liegen kann (es passiert auch wenn man das Programm über einen Beamer anzeigt)?

Schöne Grüße
Quaneu

09.10.2012 - 10:44 Uhr

Hallo MrSparkle,

also die Maus bewege ich nicht an diese Stelle. Aber ich glaube dies muss man auch nicht machen, da man mit SendMessage() auch einen Mausklick schicken kann, wenn das Fenster minimiert ist. Deshalb gibt man auch das Handle des Controls an. Zumindest habe ich das so verstanden.

09.10.2012 - 09:19 Uhr

Hallo,

ich versuche nun schon seit 2 Tagen mit SendMessage(...) das ContextMenu eines TreeViews anzuzeigen und darin dann ein Item anzuklicken. Doch leider bekomme ich das ContextMenu nicht auf...

Die GUI wurde in Forms erstellt und das ContextMenu ist ein ContextMenuStrip.

Mein erster versuch war ein Rechts-Klick:


public static void RightMouseClick(IntPtr handle, Int32 x, Int32 y)
{
	Int32 coordinates = x | (y << 16);
	Win32.SendMessage(handle, Win32.WM_RBUTTONDOWN, (IntPtr)0x0, (IntPtr)coordinates);
	Win32.SendMessage(handle, Win32.WM_RBUTTONUP, (IntPtr)0x0, (IntPtr)coordinates);
	Application.DoEvents();
}

Der zweite sah wie folgt aus:


public static void ContextMenuClick(IntPtr handle)
{
	Win32.SendMessage(handle, Win32.WM_KEYDOWN, (IntPtr)Win32.VK_APPS, (IntPtr)0x0);
	Win32.SendMessage(handle, Win32.WM_KEYUP, (IntPtr)Win32.VK_APPS, (IntPtr)0x0);
	Application.DoEvents();
}

Doch leider beide ohne Erfolg. Handle war in beiden Fällen das Handle des TreeViews.

Es wird nie das Event _treeViewContextMenuStrip_Opening(...) ausgelöst.

Falls mir jemand weiterhelfen könnte, wäre ich sehr dankbar.

Schöne Grüße
Quaneu

08.10.2012 - 10:44 Uhr

Sorry hab den Fehler gefunden....

Das Problem ist wohl, dass ich nicht Application.DoEvents() aufgerufen habe und somit die GUI nicht "aktuell" ist und somit alles aus dem Ruder läuft.

Schöne Grüße
Quaneu

08.10.2012 - 10:13 Uhr

Jetzt bin ich mir nicht sicher ob es nicht besser wäre einen neuen Beitrag zu erstellen...

Ich hätte nämlich noch im Bezug auf das Testen mit SendMessage() noch eine Frage:

Wieso funktioniert SendMessage in diesem Fall nicht?


DataGridView dataGrid = Reflector.GetFieldValue<DataGridView >(userControl, "_dataGrid");
Rectangle rctCell = dataGrid.GetCellDisplayRectangle(row.Cells["_nameColumn"].ColumnIndex, row.Index, true);
pos = new Point(rctCell.X + 10, rctCell.Y + rctCell.Height / 2);
GuiSimulation.LeftMouseClick(dataGrid, pos.X, pos.Y);
GuiSimulation.LeftMouseClick(dataGrid, pos.X, pos.Y);

DataGridViewTextBoxEditingControl dataGridViewTextBoxEditingControl = (DataGridViewTextBoxEditingControl)dataGrid.EditingControl;
GuiSimulation.SetText(dataGridViewTextBoxEditingControl, "Test");


public static void LeftMouseClick(Control control, Int32 x, Int32 y)
{
	Int32 coordinates = x | (y << 16);
	Win32.SendMessage(control.Handle, Win32.WM_LBUTTONDOWN, (IntPtr)0x0, (IntPtr)coordinates);
	Win32.SendMessage(control.Handle, Win32.WM_LBUTTONUP, (IntPtr)0x0, (IntPtr)coordinates);
}

Doch wird durch


GuiSimulation.LeftMouseClick(dataGrid, pos.X, pos.Y);

kein MouseClick auf dem DataGridView ausgelöst... Und ich versuche schon das ganze WE herauszufinden warum...

Viele schöne Grüße
Quaneu

05.10.2012 - 15:04 Uhr

Hallo herbivore,

normal laufen die Tests auch auf dem BuildServer bei jedem commit an. Doch soll es auch möglich sein diese lokal laufen zu lassen ohne das die Maus wild am Bildschirm hin und her springt.
Natürlich gebe ich Dir aber vollkommen Recht mit dem was Du sagst.

Habe jetzt das Problem endlich lösen können 😃

Mit Sendmessage(...) klappt es wunderbar. Und ich denke damit bin ich noch näher an der tatsächlichen Situation (zumindest ein Stückchen).

Viele Grüße und vielen Dank
Quaneu

04.10.2012 - 13:25 Uhr

Danke für Deine Hilfe.

Das mit dem Reflector werden ich gleich mal probieren. Und das mit

auf einer tieferen Ebene zu simulieren

habe ich mir schon überlegt. Doch dazu wird die Maus "wirklich" bewegt. Dies wollte ich vermeiden. Denn wenn die Tests lokal laufen würden, wäre es in dieser Zeit nicht mehr möglich an dem Rechner zu arbeiten, da die Maus immer "springt" usw.

04.10.2012 - 13:08 Uhr

Jetzt hätte ich noch eine Frage in diesem Zusammenhang:

Wenn ich z.B. auf eine CheckBox (in einem DataGridView) klicke werden eine Reihe von Events gefeuert. Z.B. Click -> MouseClick -> ... usw.
Wenn ich nun Click "simuliere", indem ich OnClick aufrufe passiert dies leider nicht. Gibt es eine Möglichkeit das diese Event-Kette trotzdem durchlaufen wird?

04.10.2012 - 09:24 Uhr

Hallo zusammen,

ich schreibe gerade Tests für meine GUI. Früher habe ich TestComplete benutzt, doch nun will ich davon weg und teste meine GUI "selbst".
Dazu benutzt ich Reflection, wenn ich z.B. einen Button-Click simulieren will, rufe ich OnClick auf.
Doch leider komme ich mit dem DataGridView nicht weiter. Der zu testende Code hat das Event CellContentClick abonniert und wertet darin EditedFormattedValue von einer DataGridViewCheckBoxCell aus.

Nun passiert aber folgendes:
Wenn ich im normalen Betrieb auf die DataGridViewCheckBoxCell klicke (checked == false) dann ist EditedFormattedValue == true. Passt.

Im Test löse ich nun OnCellContentClick aus um den Klick auf die CheckBox zu simulieren (checked == false) , doch nun ist EditedFormattedValue == false.

Und ich komm einfach nicht dahinter wieso dies so ist.

Ich habe auch schon versucht ein MouseClick auf dem DataGridView zu simulieren, doch leider wird hier "nur" das Event MouseClick ausgelöst und sonst nichts mehr. Wenn ich im "normalen" Betrieb auf die CheckBox klicke wird auch MouseClick ausgelöst und dann aber auch CellContentClick...

Hätte jemand vielleicht einen Anhaltspunkt, wie ich dieses Problem lösen könnte?

Schöne Grüße
Quaneu

26.09.2012 - 11:51 Uhr

Ok 😃

Mit dem Wrapper würde der Code natürlich anders aussehen:


private StatusWrapper[] _status= new StatusWrapper[] 
			{	new StatusWrapper(eStatus.None), 
			        new StatusWrapper(eStatus.Ok), 
			        new StatusWrapper(eStatus.Not_Ok) };

public StatusWrapper[] Status
{
	get { return this._status; }
}

Hiermit funktioniert das Binding perfekt (wenn ich ValueMember auf Status und DisplayMember auf DisplayName in der ComboBox setze).

Mit diesem Code bekomme ich die besagt Excepetion:


private eStatus[] _status= new eStatus[]{ eStatus.None, eStatus.Ok, eStatus.Not_Ok};
public eStatus[] Status
{
    get { return this._status; }
}

Wobei ich mir hier auch nicht sicher bin auf was ich ValueMember und DisplayMember in der ComboBox setzen soll.

Doch ich hätte es eben gern ohne den Wrapper und nur mit dem eStatus[].

26.09.2012 - 11:31 Uhr

was ist das denn für eine merkwürdige Konstruktion:

Entschuldige bitte. War nicht aus dem Quellcode sondern Freitext. Hab es soeben behoben.

Der Wrapper würde so aussehen:


public class StatusWrapper
{
	public StatusWrapper(eStatus status)
	{
		this.Stauts= status;
	}

	public eStatus Status
	{
		get;
		private set;
	}

	public String DisplayName
	{
		get { return this.Status.ToString(); }
	}
}

Hier kann ich den ValueMember auf Status setzen und DisplayMember auf DisplayName. Dann klappt es.

Die Exception kommt immer dann wenn ich z.B. das Control, in dem dieses Binding definiert ist, gezeichnet werden soll. Also z.B. wenn ich es per Code in ein Panel setze. Doch leider komme ich eben mit dieser Exception nicht sehr viel weiter...

Hier einmal der StackTrace:> Fehlermeldung:

bei System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value)
bei System.Windows.Forms.Binding.SetPropValue(Object value)
bei System.Windows.Forms.Binding.PushData(Boolean force)
bei System.Windows.Forms.Binding.UpdateIsBinding()
bei System.Windows.Forms.Binding.CheckBinding()
bei System.Windows.Forms.Binding.SetListManager(BindingManagerBase bindingManagerBase)
bei System.Windows.Forms.ListManagerBindingsCollection.AddCore(Binding dataBinding)
bei System.Windows.Forms.BindingsCollection.Add(Binding binding)
bei System.Windows.Forms.BindingContext.UpdateBinding(BindingContext newBindingContext, Binding binding)
bei System.Windows.Forms.Control.UpdateBindings()
bei System.Windows.Forms.Control.OnBindingContextChanged(EventArgs e)
bei System.Windows.Forms.ListControl.OnBindingContextChanged(EventArgs e)
bei System.Windows.Forms.Control.OnParentBindingContextChanged(EventArgs e)

26.09.2012 - 10:57 Uhr

Hallo zusammen,

ich versuche mich gerade am Binding in Forms.

Ich will mich an SelectedValue einer ComboBox binden, da SelectedItem mit OnPropertyChanged nicht "richtig" funktioniert. Leider funktioniert das nicht wie gewünscht bzw. nur über einen Umweg, der mir nicht gefällt...

Ich habe in meinem Controller folgendes Property (wobei eStatus ein enum ist)


private eStatus[] _status= new eStatus[]{ eStatus.None, eStatus.Ok, eStatus.Not_Ok};
public eStatus[] Status
{
	get { return this._status; }
}

In der View habe ich nun folgendes:


this._statusComboBox.DataSource = this._controller.Status;
this._statusComboBox.DataBindings.Add("SelectedValue", this._controller, "Test.Status", false, DataSourceUpdateMode.OnPropertyChanged);

Doch leider bekomme ich dabei immer eine NullReferenceException (irgendow "tief unten"). Ich habe auch gelesen das man ValueMember setzten muss, wenn man an SelectedValue bindet, doch was ist das in meinem Fall?

Wenn ich nun einen Wrapper für den enum schreibe funktioniert es. Doch das finde ich nicht sonderlich schön.

Daher meine Frage, ist es möglich auch ohne den Wrapper das Binding zum Laufen zu bringen?

Schöne Grüße
Quanue

18.09.2012 - 11:35 Uhr

Hallo herbivore,

vielen Dank für deinen Hinweis. Hatte gehofft, dass es da was gibt. Setze jetzt ein "Flag", falls eine Exception auftritt, das ich bei bedarf abrufen kann.
Bin mit diesem Thema leider noch nicht so vertraut, daher die Frage 😃

Schöne Grüße
Quaneu

17.09.2012 - 13:45 Uhr

Vielen Dank erstmals, aber ich glaube leider, dass mir dies nicht weiter hilft.

Der CallBack wird ja von der API "aufgerufen", in dem CallBack werfe ich eine Exception, die den Test normalerweise stoppen sollten. Nur passiert das eben nicht, da diese Excpetion "verschluckt" wird.

Wie schaffe ich es daher, dass eine Exception die in der CallBack-Methode geworfen wird, nicht verschluckt wird?

Hier ein kleines Beispiel:


private void Listening()
{
   callback = Callback;
   handleToHook = Win32.SetWindowsHookEx(HCBT_ACTIVATE, callback, IntPtr.Zero, Win32.GetCurrentThreadId());
}

private IntPtr Callback(Int32 code, IntPtr wParam, IntPtr lParam)
{
   throw new Exception();
}

Die Excpetion in Callback() wird "verschluckt".

17.09.2012 - 12:54 Uhr

Hallo zusammen,

ich benutzt die Methode SetWindowsHookEx(...) aus der user32.dll um in Tests mit modale Dialogen umgehen zu können.
Wenn nun ein modaler Dialog aufgerufen wird, so wird ein Callback aufgerufen in dem ich z.B. schauen kann, ob es sich um einen "erwarteten" Dialog handelt oder um einen unerwarteten handelt. Bei einem "erwarteten" wird nun Test-Code für das Fenster ausgeführt und bei einem unerwarteten wird dieses Fenster über DestroyWindow(...) "geschlossen und eine Exception geschmissen. Diese wird jedoch "verschluckt"...

Daher wollte ich fragen, woran dies liegen kann und was ich machen muss, damit diese nicht mehr verschluckt wird.

Schöne Grüße
Quaneu

07.09.2012 - 14:33 Uhr

War im Release-Modus. Das mit der Beispielanwenung ist schwer.

07.09.2012 - 12:17 Uhr

Anstatt:


...
switch(xmlNode.Name)
{
   case "Person":
   Person person= new Person();
   ...
   break;
   
   ...
}

Habe ich folgendes probiert:


Dictionary<String, Action> dict = new Dictionary<String, Action>();
dict.Add("Person", () => { Person person = new Person(); ... });

...
dict[xmlNode.Name]();

Und es war bei mir um ca. 50% langsamer.

07.09.2012 - 12:01 Uhr

Ich will ohne DOM auskommen, bzw. nicht, dass der "Reader" die ganze XML in den Speicher lädt und dies macht der XmlTextReader eben nicht und mit dem XmlTextReader kenne ich leider keinen anderen Weg.

07.09.2012 - 11:39 Uhr

Ich will eine xml-Datei parsen. D.h. wenn z.B. ein Tag mit dem Namen Person kommt soll er eine Klasse Person anlegen usw. usw.
Daher muss ich die Tag Namen vergleichen und speziell darauf "reagieren".

Ich habe schon mit einem Dictionary gearbeitet die eine Action zurück gibt (ist 50% langsamer) und außerdem habe ich dann auch 260 add Aufrufe, was genau so unschön ist.

Ich weiß nicht wie man eine xml anders parsen kann. Für bessere Vorschläge bin ich immer offen 😃

Grüße
Quaneu

05.09.2012 - 22:46 Uhr

Oder schau dir mal KeyedCollection an.

Grüße
Quaneu

05.09.2012 - 22:35 Uhr

So ich hab jetzt mal einen ersten Test gemacht. Und mit switch ist es ca. 30% schneller als mit if.

Ist eine Xml-Datei mit ca. 12000 Zeilen und ca. 260 verschiedenen Tags
=> ein switch mit 230 cases oder 260 ifs.

Leider kann ich folgenden Code nicht in einer Schleife laufen lassen, da nach dem ersten Durchlauf wohl "optimiert" wird.


Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

using (FileStream SourceStream = File.Open(path, FileMode.Open))
{
	using (XmlTextReader xmlTextReader = new XmlTextReader(SourceStream))
	{
		try
		{
			xmlTextReader.WhitespaceHandling = WhitespaceHandling.None;
			Read(xmlTextReader);
		}
		catch (Exception exp)
		{
			MessageBox.Show(String.Format("Error in line {0}.\r\n{1}", xmlTextReader.LineNumber.ToString(), exp.Message), "Test", MessageBoxButton.OK, MessageBoxImage.Exclamation);
		}
	}
}

stopwatch.Stop();
ElapsedTime = stopwatch.ElapsedMilliseconds;

05.09.2012 - 18:03 Uhr

Also ich hab gelesen, dass es auf die Anzahl der cases ankommt.
Ab einer bestimmten Anzahl wird "intern" ein Dictonary benutzt.

05.09.2012 - 17:03 Uhr

Hallo zusammen,

ich habe, wie die Überschrift schon sagt, eine Frage zur Performance des XmlTextReaders.

Bisher "vergleiche" ich in einem großen Switch die Namen von Elementen


switch (xmlTextReader.Name)
{
   case "Node":
     ...
   break;

   case "Node2":
     ...
   break;

   ...
}

Nun bin ich aber gerade über die NameTable des XmlTextReaders gestolpert und frage mich nun ob es nicht schneller ist diese zu verwenden. Doch dazu muss ich aus dem switch ein if (else if ... usw.) machen um die NameTable zu verwenden. Dadurch geht mir aber die Performance des switch verloren.

Kann man diesbezüglich Aussagen machen, was nun besser bzw. schneller ist?

Switch mit String-Vergleich oder if mit Object.ReferenceEquals(...).

Schöne Grüße
Quaneu

04.09.2012 - 09:09 Uhr

Leider noch nicht. Bisher habe ich auch nur den Weg über Events gefunden.
Meine Idee war noch, mit MouseOver zu arbeiten, d.h. das Objekt im TreeView bekommt mit, wenn sich die Maus über ihm befindet und beim Rechts-Klick wird das ContextMenu für dieses aufgerufen. Doch leider habe ich noch keine Möglichkeit gefunden mich daran zu binden...

<TreeView.ItemContainerStyle>
	<Style TargetType="{x:Type TreeViewItem}">
		<Setter Property="IsExpanded"
				Value="{Binding Path=SelectedAndExpanded.IsExpanded, Mode=TwoWay}" />
		<Setter Property="IsSelected"
				Value="{Binding Path=SelectedAndExpanded.IsSelected, Mode=TwoWay}" /> 
	</Style>
</TreeView.ItemContainerStyle>

Denn in dem Style ist mir dies noch nicht geglückt...

Schöne Grüße
Quaneu

29.08.2012 - 14:34 Uhr

Wenn du den Status änderst, änderst Du nicht das Feld, sonder schon das Property "Status"?

29.08.2012 - 14:12 Uhr

Könnte ich bitte noch die CBaseKnoten Klasse sehen?

29.08.2012 - 13:43 Uhr

Im Output bzw. im Immediate Window kommen also keine Fehler? Und Du benutzt auch das Interface
INotifyPropertyChanged, damit die GUI deine Änderungen mitbekommt?

Am besten ist es Du zeigst mal wie Du die TreeViewItems erzeugst.

Noch schöner ist es natürlich, den TreeView per HierarchicalDataTemplate zu füllen. Dann hast Du alles in XAML 😃.

29.08.2012 - 12:40 Uhr

Nix zu danken .

Im Output bzw. im Immediate Window kommen also keine Fehler? Und Du benutzt auch das Interface
INotifyPropertyChanged, damit die GUI deine Änderungen mitbekommt?

29.08.2012 - 12:22 Uhr

Ich habs endlich gelöst 😃

Ich habe nun ein DP vom Typ Data in MyCustomControl, an dieses binden sich die "GUI" und auch der Style von MyCustomControl. Dadurch klappt es.

TextBox.Text (Data.Name)<-2-> Data (DP in MyCustomControl) <-1-> Data

Schöne Grüße
Quaneu

29.08.2012 - 12:12 Uhr

Hallo,

ich würde mich ganz einfach an Status binden und über einen Converter das Image bzw. den "Pfad" zurückgeben lassen.


<Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="HeaderTemplate">
                        <Setter.Value>
                            <DataTemplate DataType="my:CBaseKnoten">
                                <StackPanel Orientation="Horizontal">
                                    <Image Source="{Binding Status, Converter={StaticResource statusToImageConverter}"/>
                                    <TextBlock Text="{Binding}" Margin="5"/>
                                </StackPanel>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>

In deinem Fall könnte sein, das der DataContext nicht stimmt und somit das Binding nicht funktioniert?
Schöne Grüße
Quaneu

29.08.2012 - 10:28 Uhr

Das Control bekommt die Änderung ja mit. Doch das erste Binding (1) "verschluckt" das ein Fehler eingetreten ist.

Die Bindings laufen wie folgt:
TextBox.Text <-2-> Name (DP in MyCustomControl) <-1-> Data.Name

Hier die Implementierung:

public String Name
{
	get { return this.Data.Name; }
	set
	{
		if (this.Data.Name != value)
		{
			this.Data.Name = value;
			ValidateName();
			NotifyPropertyChanged("Name");
		}
	}
}

Wobei ValidateName() ein Dictonary _errorMessages aktualisiert. Dieses wird wie folgt verwendet:

public String this[String columnName]
{
	get { return this._errorMessages[columnName]; }
}
29.08.2012 - 09:13 Uhr

Ich verstehe nun wieso es nicht geht. Das Objekt Data hat das Interface IDataErrorInfo implementiert und validiert somit den Namen. D.h. es stellt gegebenenfalls einen Fehler fest.
In MyCustomControl wird die TextBox an Name gebunden, dies hat natürlich keine Validierung und daher bekommt die TextBox nie mit das ein Fehler vorliegt.

=> ich müsste über das Binding die Information transportieren, das ein Fehler vorliegt...

Doch leider finde ich hierfür keinen Weg.

Ich hoffe mir kann wer auf die Sprünge helfen.

Schöne Grüße
Quaneu

20.08.2012 - 11:54 Uhr

Hallo,
ich habe ein CustomControl (MyCustomControl) in dem eine TextBox enthalten ist:


<TextBox Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Name, UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True, Mode=TwoWay}" />

Der Text ist an ein DependencyProperty in MyCustomControl.cs gebunden:


public String Name
{
	get { return (String)this.GetValue(NameProperty); }
	set { this.SetValue(NameProperty, value); }
}
public static readonly DependencyProperty NameProperty = DependencyProperty.Register(
	"Name", typeof(String), typeof(MyCustomControl), new PropertyMetadata(String.Empty));

Nun verwende ich MyCustomControl wie folgt:


<controls:MyCustomControl Name="{Binding Data.Name, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>

Es klappt auch fast alles doch leider wird der rote Rahmen nie angezeigt, wenn der Name "falsch" ist. Wenn ich folgendes verwende wird der rote Rahmen gezeichnet doch leider um mein ganzes CustomControl.


<controls:MyCustomControl Name="{Binding Data.Name, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>

Daher meine Frage, wie schaffe ich es in einem CustomControl ValidatesOnDataErrors auf einzelnen Controls anzuwenden?

Grüße
Quaneu

17.08.2012 - 16:06 Uhr

Hallo zusammen,

ich versuche zur Zeit verzweifelt meinen TreeView, den über HierarchicalDataTemplate befülle mit einem ContextMenu auszustatten.

Dies wollte ich wie folgt machen:

<TreeView>
	<TreeView.ContextMenu>
		<ContextMenu ItemsSource="{Binding ContextMenuWrapper}" />
	</TreeView.ContextMenu>
</TreeView>

Dies würde auch alles klappen, doch das Problem ist nun folgendes:
Beim Rechts-Klick öffnet sich das ContextMenu, aber leider wird im TreeView dabei nicht das Item selektiert.

Ich würde gern beim Rechts-Klick das Item selektieren und dann das ContextMenu öffnen, da je nach einem das ContextMenu anders aussieht...
Doch leider bekomme ich dies mit MVVM nicht hin. Denn der einzige Weg, der mir einfällt, ist ein Event zu abonnieren und dann im ViewModel per "Hand" zu selektieren.

Ich hoffe mir kann wer aus die Sprünge helfen.
Schöne Grüße
Quaneu

06.08.2012 - 09:38 Uhr

Das weiß ich 😃

Mich hat nur deine Aussage

Wenn ich jetzt Text in der TexBox ändere wird der Setter von MyTextPropertyx aufgerufen...

bisschen stutzig gemacht. Daher wollte ich dies nur erwähnen.

06.08.2012 - 09:22 Uhr

Hallo,

probier mal


 <TextBox Text="{Binding MyTextProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

Schöne Grüße
Quaneu

02.08.2012 - 09:32 Uhr

Hallo xxxprod,

vielen Dank für Deine Hilfe. Genau diese Lösung habe ich gerade probiert 😃


sealed class SelectedWrapper<T> : NotificationHelper
{
	#region Private Members
	protected Boolean _isSelected;
	protected Boolean _isExpanded;
	#endregion

	#region EventHandler
	public event EventHandler<ValueEventArgs<Boolean>> SelectionChangedInTreeView;
	#endregion

	public SelectedWrapper(T content)
	{
		this.Content = content;
	}

		
	#region Properties
	public T Content { get; private set; }

	public Boolean IsSelected
	{
		get { return this._isSelected; }
		set
		{
			if (this._isSelected != value)
			{
				this._isSelected = value;
				OnSelectionChanged(this._isSelected);
				NotifyPropertyChanged("IsSelected");
			}
		}
	}

	public Boolean IsExpanded
	{
		get { return this._isExpanded; }
		set
		{
			if (this._isExpanded != value)
			{
				this._isExpanded = value;
				NotifyPropertyChanged("IsExpanded");
			}
		}
	}
	#endregion

	#region Private Methods
	private void OnSelectionChanged(Boolean isSelected)
	{
		EventHandler<ValueEventArgs<Boolean>> handler = this.SelectionChangedInTreeView;
		if (handler != null)
		{
			handler(this, new ValueEventArgs<Boolean>(isSelected));
		}
	}
	#endregion
}

Mit dem Virtualizingstackpanel muss ich mir dann noch was überlegen, aber ich denke dies ist die "schönste" Lösung.

Wobei ich jetzt natürlich für jedes ViewModel, dass diesen Wrapper benutzt wiederrum Wrapper schreiben muss, die nicht generisch sind, damit ich diese im HierarchicalDataTemplate verwenden kann... ahhhhhhhh

Grüße
Quaneu