Laden...

Forenbeiträge von blackdynamic Ingesamt 51 Beiträge

27.10.2011 - 10:14 Uhr

Ich verwende WPF, aber die konkreten asynchronen Services, welche dann von der oben geposteten Klasse abgeleitet sind, werden dem PersonenManager über einen IOC Container injeziert.
Dieser Container registriert die asynchronen Services innerhalb der App.xaml.cs also direkt im GUI-/Main-Thread.

Ich hoffe das hilft euch weiter ..

27.10.2011 - 09:55 Uhr

Ich bin mittlerweile auf die Erklärung von herbivore bezüglich meines Problems gestoßen:
[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)

Allerdings befindet sich dort folgende Aussage:

BackgroundWorker

Statt mit extra Threads und Control.Invoke, kann man auch mit der BackgroundWorker-Klasse ungültige threadübergreifende Vorgänge vermeiden. Dazu müssen bei BackgroundWorker alle Zugriffe auf das GUI einfach aus den ProgressChanged- oder RunWorkerCompleted-EventHandlern durchgeführt werden. Wenn man sich daran hält, ist explizites Control.Invoke bei BackgroundWorker nicht erforderlich, denn die genannten EventHandler werden hinter den Kulissen automatisch per Control.BeginInvoke aufgerufe

Und das ist es ja, was ich auch erwartet habe ... vielleicht zum besseren Verständniss ein Ausschnitt aus meinem BackgroundWorker:


public abstract class MyAsyncServiceBase
{
	(...)
	protected void AnyGenericInvoke<TAsyncRequest, TAsyncResponse>(TAsyncRequest asyncRequest, Func<TAsyncRequest, TAsyncResponse> method, Action<TAsyncResponse> asyncCallback)
	{
		BackgroundWorker worker = new BackgroundWorker();

		worker.DoWork += (sender, args) =>
		{
			args.Result = method(asyncRequest);
		};

		worker.RunWorkerCompleted += (sender, args) =>
		{
			if (asyncCallback != null)
				asyncCallback(args.Result as TAsyncResponse);
		};

		using (worker) 
		{ 
			worker.RunWorkerAsync(); 
		}
	}
}

Ich hoffe es gibt hier jemanden, der mich "erleuchten" kann ..

*edit Ja, den habe ich auch gerade gefunden, den Thread. Aber wie ich ja oben zitiert habe sagt auch dieser aus, dass es mit dem Backgroundworker so funktionieren sollte..
In schmeisse in keiner asynchronen Methode ein Event.

27.10.2011 - 01:12 Uhr

Hallo liebe Community,

ich habe zwei Probleme bei folgendem Szenario:


public class PersonViewModel()
{
	public ObservableCollection<Person> People;
	private IPersonManager _personManager;

	public PersonViewModel(IPersonManager personManager)
	{
		_personManager = personManager;
		People = new ObservableCollection<Person>();
		_personManager.People.CollectionChanged += ((object sender, NotifyCollectionChangedEventArgs e) => this.People = _personManager.People);
	}
}

public class PersonManager
{
	public ObservableCollection<Person> People;
	private IAsyncPersonService _asyncPersonService;
	private IPersonChangeInitiator _initiator;
	
	public PersonManager(IAsyncPersonService asyncPersonService, IPersonChangeInitiator initiator)
	{
		People = new ObservableCollection<Person>();
		_asyncPersonService = asyncPersonService;
		_initiator = initiator;
		_initiator.OnAddNewPerson += onAddNewPerson;
	}
	
	public void onAddNewPerson()
	{
		_asyncPersonService.InvokeGetAnyPerson(new GetAnyPersonRequest(), invokeGetAnyPersonCallback);
	}
	
	private void invokeGetAnyPersonCallback(GetAnyPersonResponse response)
	{
		if(response != null)
		{
			Person person;
			
			if(response.IsNewPerson)
			{
				person = response.Person;
				People.Add(person);
			}
			else
				// Für dieses Beispiel setze ich einfach mal voraus, dass der Nachname eindeutig ist
				person = People.GetPersonByName(response.Person.Name);
				
			doAnythingWithPerson(person);
		}
	}
}

Der AsyncPersonService startet die aufgerufene Methode über einen Backgroundworker asynchron.

Wenn der PersonChangeInitiator das erste mal das OnAddNewPerson-Event schmeisst, und es sich um eine neue Person handelt, wird diese ohne Probleme der Liste im PersonManager hinzugefügt
und das CollectionChanged-Event kann ohne Probleme im View-Model gefangen werden. Das bedeutet, auch die Liste im ViewModel hat nun die neue Person.

Problem 1:
Schmeisst der PersonChangeInitiator jedoch ein zweites mal dieses Event, natürlich dieses mal mit anderen Werten um noch eine andere Person anzulegen, bekomme ich bei "People.Add(person);" folgende Exception:> Fehlermeldung:

Von diesem CollectionView-Typ werden keine Änderungen der "SourceCollection" unterstützt, wenn diese nicht von einem Dispatcher-Thread aus erfolgen

Problem 2:
Wird nach dem Ersten OnAddNewPerson-Event vom PersonChangeInitiator erneut das OnAddNewPerson-Event geschmissen, und in der GetAnyPersonResponse befindet sich keine neue Person sondern die gerade zuvor angelegte,
kann ich mir das zuvor angelegte Personenobjekt über den Namen aus der People-Liste holen("People.GetPersonByName") und in der Methode "doAnythingWithPerson(person)" zwar verändern,
dass ViewModel wird darüber allerdings nicht mehr über das CollectionChanged-Event der People-Liste benachrichtigt.

Ich vermute mal, dass diese beiden Probleme miteinander zusammenhängen, richtig?

Ich hatte schon vor etwas längerer Zeit mal Probleme mit Threading, Dispatcher usw. Hatte damals aber auch keine MVVM-Anwendung und habe es einfach im Codebehind über so einen Dispatcher-Workaround gedreht.
Da ich mich damals aber noch nicht so gut mit Programmierung auskannte, war der Code sehr unübersichtlich und schlecht geschrieben, auch wenn er funktionierte.

Deshalb hatte ich mich zum Entwurf einer komplett neuen Struktur entschlossen, die nun wie eben gesagt auf dem MVVM Pattern basiert und mit asynchronen Methoden arbeitet.
Ich dachte eigentlich, durch das Verwenden des Callbacks bei asynchronen Methoden könnte ich sicher stellen, dass ich immer wieder im gleichen Thread lande, nachdem die asynchrone Methode durchgelaufen ist.
Von daher hatte ich mir davon eigentlich erhofft, die Dispatcher-Problematik umgangen zu haben.

Könnt ihr mir eventuell weiter helfen, was ich verändern / anpassen muss um die Probleme zu beheben?
Und wo liegt der Fehler in meiner Denkweise, bezogen auf das Threading-Verhalten der MVVM Struktur mit asynchronen Methoden?

Viele Grüße
blackdynamic

29.09.2011 - 12:20 Uhr

Genial, damit läuft der Test durch! Danke 😃

29.09.2011 - 11:44 Uhr

Vielen Dank für eure Geduld und Eure Hilfe!

Ich war auch der Meinung das die Referenz übergeben wird und genau das war auch der Grund warum ich so ratlos war.

Letztendlich lag das Problem nun darin, dass die Peson in der Liste zwar aktualisiert wurde (was ich auf deine Anmerkung hin direkt im Callback getestet habe) aber ich in meinem Unit Test noch die alte Liste hatte weil die Überprüfung des Tests nicht gewartet hat, bis der Callback fertig gelaufen war.

Das bedeutet der Fehler lag in meinem Unit Test, nochmals vielen Dank 😃

29.09.2011 - 11:19 Uhr

Die Person befindet sich in einer ObservableCollection

29.09.2011 - 10:54 Uhr

Nein, weil ich nicht wirklich weiss wo ich es fangen sollte um mein Problem zu lösen. Ich will ja bloß, dass die Person aus der Liste innerhalb der Liste aktualisiert wird wenn eine Eigenschaft der Person in einer asynchronen Methode geändert wird.

28.09.2011 - 23:26 Uhr

Ich habe die Person Klasse nun wie folgt angepasst:


public class Person : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return this._name; }

set
{
if (value != this._name)
{
this._name = value;
NotifyPropertyChanged("Name");
}
}
}

public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}

public Person()
{
Name = "Olaf";
}
}

Es funktioniert allerdings leider trotzdem noch nicht.
Beim debuggen fällt auf, dass diese Bedingung "PropertyChanged != null" immer false ist und somit das Event nicht geschmissen wird.
Das diese Bedingung false ist sagt ja aus, dass es keine Abonnenten für das Event gibt, wisst ihr wo mein Fehler liegt?

28.09.2011 - 19:24 Uhr

Hallo liebe Community,

ich habe folgendes Problem:
Wenn ich eine Eigenschaft eines Objektes, welches sich in einer Liste von Objekten befindet, während einer asynchron laufenden Methode verändere, bekommt der Thread, welcher die asynchrone Methode aufgerufen hat, die Veränderung an dem Objekt nicht mit.
Könnt ihr mir sagen was ich dafür verändern muss?

Hier ein kleines Beispiel:

ViewModel.cs



public ObservableCollection<Person> Persons;

...

public void onAddPerson(object sender, EventArgs e)
{
// Der Name der Person wird im Konstruktor auf Olaf gesetzt. Ob man das so machen würde
// sei dahin gestellt, es geht nur darum meine Situation an einem Beispiel zu
// verdeutlichen
var person = new Person();
Persons.Add(person);

var request = new ChangePersonRequest(person);

// Der asynchrone Aufruf erfolgt über einen Backgroundworker
_asyncService.invokeChangePerson(request, changePersonCallback);
}

private void changePersonCallback(ChangePersonResponse response)
{
// An dieser Stelle ist der Name der Person in der Liste immernoch Olaf.
// Die Person soll aber den Namen haben, der ihr in der asynchronen Methode zugewiesen wurde
persons[0].Name
}

Service.cs


....
public ChangePersonResponse ChangePerson(ChangePersonRequest request)
{
request.CurrentPerson.Name = "Max";

var response = new ChangePersonResponse(request.CurrentPerson);

return response; 
}

ChangePersonResponse.cs


....
public class ChangePersonResponse
{
public Person CurrentPerson {get; set;}

public ChangePersonResponse(Person person)
{
CurrentPerson = person
}
}

ChangePersonRequest.cs


public class ChangePersonRequest
{
public Person CurrentPerson {get; set;}

public ChangePersonRequest(Person person)
{
CurrentPerson = person
}
}

Person.cs


public class Person
{
public string Name {get; set;}

public Person()
{
Name = "Olaf";
}
}

09.09.2011 - 12:08 Uhr

Ich verwende zur Zeit asynchrone Methodenaufrufe, die denen hier im Kapitel 5.5 ([Artikel] Multi-Threaded Programmierung) sehr ähneln.

Das heisst, das Senden der Daten soll ebenfals in so einem asnychronen Methodenaufruf erfolgen.

Der Service zum senden der Daten würde der asynchronen Methode als request Parameter übergeben werden. Dürfte ich von meiner asynchronen Methode aus, die sich hinter dem asynchronen Proxy befindet, auf eine statische SyncQueue zugreifen, die sich in dem ViewModel befindet das die asynchrone Methode aufruft?
Auch in Bezug auf das MVVM Pattern..

Ich hoffe ihr versteht was ich meine 😃

Viele Grüße

*edit -> Oder wie wäre es, wenn ich die SyncQueue in das request objekt einbauen würde? Wäre das "sauberer"?

09.09.2011 - 11:39 Uhr

Vielen Dank 😃

09.09.2011 - 11:23 Uhr

Vielen Dank für eure schnellen Antworten. 😃

Der Service schmeisst zusätzlich noch Events, wenn er selbst Daten empfangen hat.
Kann das in Kombination mit den SyncQueue zu Komplikationen führen?

09.09.2011 - 11:02 Uhr

Sehr geehrte Community,

ich stehe zur Zeit vor folgendem Problem:
Ich habe einen Service, der es mir ermöglicht Daten zu versenden.
Das senden der Daten würde ich gerne asynchron über einen Backgroundworker laufen lassen.
Es müssen von mehreren verschiedenen Stellen aus Daten gesendet werden können.

Nun zu meinen zwei Fragen:

  1. Ist die wahrscheinlichkeit groß, dass es dabei zu einer Kollision kommt?
  2. Wie könnte ich so eine Kollision verhindern? Am besten wäre wenn ich einem Thread sagen könnte: "Wenn gerade jemand anders Daten sendet, dann warte bis der damit fertig ist und fang dann erst an zu senden"

Ich würde mich freuen, wenn ihr mir helfen könnt.

Viele Grüße
blackdynamic

08.08.2011 - 12:50 Uhr

Schade das mir hierbei wohl keiner Helfen kann ...
Dann schraube ich meine Wünsche ein wenig zurück.

Kann mir denn vielleicht jemand sagen wie ich einfach eine Navigation bauen kann die Submenüs hat? Lassen wir die effekte einfach mal weg, von mir aus kann das auch einfach eine ganz normale Liste sein wie sie hier im Forum auf der linken Seite ja auch zu sehen ist.

Viele Grüße

05.08.2011 - 09:31 Uhr

Hallo Community,

ich würde gerne auf meiner Silverlight Website eine animierte Navigationsbar verwenden.

Unter einer animierten Navigationsbar verstehe ich, dass Submenüs "herausfahren" wenn ich mit der Maus über ein
Element der Navigationsbar gehe.

Kann mir jemand sagen wie man soetwas am besten macht, bzw. wo ich ein tutorial dazu finden kann?

Viele Grüße

04.08.2011 - 22:23 Uhr

Hallo,

falls noch jemand dieses Problem hat:

Dynamically apply and change Theme with the Silverlight Toolkit

Dieser Link hat mir letztendlich geholfen.

Viele Grüße.

04.08.2011 - 21:42 Uhr

Hallo liebe Community,

ich habe folgendes Silverlight Toolkit installiert: http://silverlight.codeplex.com/releases

(Nicht das für Windowsphone sondern das normale)

Dort drin sind Themes enthalten, aber ich habe nun seit stundenlanger Recherche keine Möglichkeit gefunden, diese in eine ganz simple HelloWorld Website so einzubauen das sie funktionieren. Ich kann sie zwar so einbauen das es beim compilieren keinen Fehler gibt, aber dann wird mir auf der Seite nichts angezeigt.

Kann mir jemand von euch sagen, wie ich dieses Themes korrekt verwenden kann so das sie auch angezeigt werden?

Ich wäre euch sehr dankbar ...

Viele Grüße
blackdynamic

09.02.2011 - 09:52 Uhr

Hallo Liebe Community,

gibt es eine Möglichkeit der ComboBox zu sagen, dass sie ein Item nur dann selektieren soll, wenn es wirklich genau (!) mit der Eingabe in der edtitierbaren ComboBox übereinstimmt?

Denn ich habe z.Z. das Problem, wenn ich zum Beispiel "Micha" eingebe, wird "Michael" zwar richtig ausgewählt, wenn ich dann aber das "a" am Ende löschen und durch ein "s" ersetze, bleibt Michael markiert. Meine Erwartungshaltung wäre allerdings, dass die Markierung direkt verschwindet, wenn die Eingabe nicht mehr genau mit einem der Items übereinstimmt.

Meine ComboBox:


<ComboBox Height="30" VerticalAlignment="Top" IsEditable="True" IsTextSearchEnabled="True" Margin="10" KeyDown="ComboBox_KeyDown" IsSynchronizedWithCurrentItem="True">
			<ComboBoxItem>
				<TextBlock Text="Michael"/>
			</ComboBoxItem>
			<ComboBoxItem>
				<TextBlock Text="Mike"/>
			</ComboBoxItem>
			<ComboBoxItem>
				<TextBlock Text="Olaf"/>
			</ComboBoxItem>
</ComboBox>

Gibt es irgendein Attribut was man bei der CB evtl. setzen kann um das zu ermöglichen? Habe mir schon den MSDN Eintrag zur CB durchgelesen aber keinen Hinweis gefunden.

Klar könnte man sowas auch selber schreiben aber ich denke sowas muss die CB doch auch standardmäßig unterstützn oder ...?

13.12.2010 - 13:05 Uhr

Hallo Community,

ich habe das Problem, dass ich beim Starten meiner Anwendung den Fokus auf dem ersten TabItem meines tabControls haben möchte.
Jedoch liegt der Fokus zu Begin auf dem Control, dass NACH dem TabControl den geringstens TabIndex hat.
Ich habe das Gefühl, dass der TabIndex bei dem TabControl nicht beachtet wird.

Hier mein Code:


<Window x:Class="TabItemSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="800" Width="800">
    <StackPanel>
        <TabControl TabIndex="300" Name="TabControl1">
                <TabItem Header="TabItemVonTabControl1" TabIndex="301">
                    <StackPanel>
                        <TextBox Name="TextBox1" Margin="10" TabIndex="302"/>
                        <ComboBox Name="ComboBox1" Margin="10" TabIndex="303"/>
                        <Button Name="Button1" Margin="10" TabIndex="304"/>
                        <TextBox Name="TextBox2" Margin="10" TabIndex="305"/>
                    </StackPanel>
                </TabItem>
            </TabControl>
        <TextBox Name="TextBox3" Margin="10" TabIndex="200"/>
        <Button Name="Button2" Margin="10" TabIndex="201"/>
        <TabControl TabIndex="100" Name="TabControl2">
            <TabItem Header="TabItemVonTabControl2" TabIndex="101">
                <StackPanel>
                    <TextBox Name="TextBox4" Margin="10" TabIndex="102"/>
                    <ComboBox Name="ComboBox2" Margin="10" TabIndex="103"/>
                    <Button Name="Button3" Margin="10" TabIndex="104"/>
                    <TextBox Name="TextBox5" Margin="10" TabIndex="105"/>
                </StackPanel>
            </TabItem>
        </TabControl>
        <TextBox Name="TextBox6" Margin="10" TabIndex="400"/>
        <Button Name="Button4" Margin="10" TabIndex="401"/>
    </StackPanel>
</Window>

Bitte beachtet, dass TabControl1 einen **höheren ** TabIndex hat als TabControl2 und somit eigentlich erst TabControl2 den Fokus erhalten sollte.

Trotzdem ist die Fokusreihenfolge wie folgt:

  • TextBox3
  • Button2
  • TextBox6
  • Button4
  • TabControl1
  • TextBox1
  • ComboBox1
  • Button1
  • TextBox2
  • TabControl2
  • TextBox4
  • ComboBox2
  • Button3
  • TextBox5

Könnt ihr mir sagen, wie ich die TabControls richtig in die Tab-Reihenfolge einbauen kann?

Viele Grüße.

06.12.2010 - 09:48 Uhr

Hallo Community,

ich möchte meine Combobox mit einer Autovervollständigung ausrüsten.
Die "Suchfunktion" habe ich schon benutzt, allerdings ergab sie keine Treffer.

Hier ist mein Code-Snippet:


MainWindow.xaml:

<ComboBox Height="30" Width="200" IsEditable="True" ItemsSource="{Binding}" IsTextSearchEnabled="False" Name="comboBox">
            <ComboBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel IsVirtualizing="True" IsItemsHost="True" />
                </ItemsPanelTemplate>
            </ComboBox.ItemsPanel>
            
</ComboBox>

MainWindow.cs:

public MainWindow()
        {
            InitializeComponent();

            List<String> names = new List<string>();
            names.Add("Michael");
            names.Add("Mike");
            names.Add("Manuel");
            names.Add("Olaf");
            this.DataContext = names;
            comboBox.Loaded += delegate
            {
                TextBox textbox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox;
                Popup popup = comboBox.Template.FindName("PART_Popup", comboBox) as Popup;

                textbox.AutoWordSelection = false;

                if (textbox != null)
                {
                    textbox.TextChanged += delegate
                    {
                        if (textbox.Text != String.Empty)
                        {
                            popup.IsOpen = true;
                            comboBox.Items.Filter += text =>
                                {
                                    if (text.ToString().Contains(textbox.Text))
                                        return true;
                                    return false;
                                };
                        }
                        else
                        {
                            popup.IsOpen = false;
                            comboBox.Items.Filter = null;
                        }
                    };
                }
            };
        }


Ich habe nun 2 Probleme:

  1. Wenn ein Buchstabe geschrieben wird, wird dieser direkt zu Beginn markiert.
    Das bedeutet es ist nicht möglich, z.B. "Michael" hintereinander zu schreiben.
    Denn das "M" wird direkt markiert, sodass im Endeffekt dann "ichael" in der Textbox steht. Man muss also erst "M" schreiben, dann die Markierung per Hand wegmachen und "ichael" hinterher schreiben.

Gibt es eine Möglichkeit, diese automatische Markierung nach einem Zeichen auszustellen?

  1. Wenn ich einen Namen ausgesucht habe, und diesen aus der Textbox lösche bleibt er trotzdem in der Textbox ausgewählt.
    Im Debugger ist zu sehen, dass das TextChanged Event 2 mal geschmissen wird. Zuerst mit dem Text "", was meiner Erwartungshaltung entspricht.
    Daraufhin wird auch der Filter der Combobox (vermutlich) korrekt gesetzt.
    Das Problem ist nun, dass danach direkt noch ein TextChanged Event geschmissen wird, welches der Textbox wieder den Wert gibt, den sie vorher hatte. Ich habe keine Ahnung wer dieses Event schmeißt und warum es plötzlich den Wert der Textbox wieder zurück setzt.

Könnt ihr mir sagen wie ich dieses zweite TextChanged Event unterbinden kann und wo es her kommt bzw. wer es schmeißt?

Ich würde mich freuen, wenn ihr mir helfen würdet.

Viele Grüße

08.10.2010 - 15:32 Uhr

Du kannst zum Beispiel einen OR-Mapper wie NHibernate verwenden. Der übernimmt dann das Speichern und auslesen aller Entitäten für dich.

07.10.2010 - 01:18 Uhr

Hallo Community,

ich habe mich gerade ein wenig mit den Validierungsmöglichkeiten in WPF auseinandergesetzt.

Nun kann man beispielsweise beim Validieren einer Textbox ein ErrorTemplate definieren, dass das Aussehen der Textbox im Falle eines Fehlers beschreibt.

Zur Zeit wird mein Fenster nach Auftreten eines Fehlers mit einem normalen roten Ramen umrundet.
Ich würde diesen Ramen gerne gegen einen DropShadowEffect austauschen, so wie ich ihn in der Textbox darunter (ohne Fehlerbehandlung) implementiert habe.

Hier meine XAML-Datei:


<Window x:Class="SimpleValidationSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:SimpleValidationSample"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <local:Person x:Key="data" />
        <ControlTemplate x:Key="TextBoxErrorTemplate" TargetType="Control">
            <WrapPanel ClipToBounds="False" >
                <Border BorderBrush="Red" BorderThickness="1">
                    <AdornedElementPlaceholder Name="adornedElement" />
                </Border>
                <TextBlock Text="{Binding ElementName=adornedElement,
                                          Path=AdornedElement.(Validation.Errors),
                                          Converter = {local:ValidationErrorToErrorMessageConverter}}"
                           FontSize="12"
                           Foreground="Red"
                           Margin="5 0 0 0"/>
            </WrapPanel>
        </ControlTemplate>
    </Window.Resources>

    <Window.DataContext>
        <Binding Source="{StaticResource data}" />
    </Window.DataContext>

    <StackPanel>
        <TextBox Name="txt" VerticalAlignment="Top" Margin="5, 20, 0, 0" Height="20" Width="130" ToolTip="Der Username darf maximal 15 Zeichen lang sein" Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}">
            <TextBox.Text>
                <Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <local:NameValidator/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox Margin="5, 20, 0, 0" Height="20" Width="130">
            <TextBox.Effect>
                <DropShadowEffect ShadowDepth="0" Color="Red" BlurRadius="5" />
            </TextBox.Effect>
        </TextBox>
    </StackPanel>
</Window>

Folgende Lösung habe ich bereits versucht:


                    <AdornedElementPlaceholder Name="adornedElement">
                        <AdornedElementPlaceholder.Effect>
                            <DropShadowEffect ShadowDepth="0" Color="Red" BlurRadius="5" />
                        </AdornedElementPlaceholder.Effect>
                    </AdornedElementPlaceholder>

Diese Lösung lässt sich zwar kompilieren, hat aber keinerlei Auswirkungen auf die Ansicht der Textbox beim Auftreten eines Fehlers.

Viele Grüße
blackdynamic

16.09.2010 - 22:25 Uhr

Ja, der Expander macht eigentlich schon das richtige, nur das er den Content nach unten ausklappt, und ich möchte gerne das sich der Header praktisch mit nach oben schiebt.
Desweiteren würde ich dir Geschwindigkeit des Hochklappens gerne regulieren.

Das ich die Reaktion auf das Mouseover mit Triggern lösen kann habe ich bereits verwendet.

Mein Problem liegt darin, dass sich der Content Bereich der Groupbox während der ANimation vergrößern soll, ohne das sich der Header und der Text im Header dabei verzerren (d.h. mit vergrößern)

16.09.2010 - 22:06 Uhr

Hallo Community,

ich versuche gerade meine Kenntnisse zum Thema Animationen in WPF ein wenig zu erweitern.
Nun wollte ich mal versuchen, eine Groupbox ausklappen zu lassen, sobald der Mauszeiger darüber geht.

Ich arbeite mit Expression Blend, habe aber leider keine Möglichkeit gefunden, diese Animation zu entwickeln.
Ich möchte innerhalb meines Timestamps die Groupbox vergrößern.
Wenn ich nun auf 2 Sekunden in der Zeitleiste klicke und danach die Groupbox größer ziehe wird alles mit vergrößert (Schriftart, Header, ...) sodass man praktisch keinen Platz für Inhalt dazu gewinnt, sondern lediglich alles größer wird.

Ich habe auch schon versucht ein Template für eine GroupBox anzulegen und dieses dann entsprechend zu animieren, leider hat das aber auch nicht zum Ziel geführt.

Ich würde mich freuen, wenn mir jemand von euch weiter helfen könnte.

Viele Grüße
blackdynamic

31.08.2010 - 00:18 Uhr

Der Eazfuscator.NET obfuscator sollte an dieser Stelle ebenfalls genannt werden.
Eazfuscator.NET

Ich habe nun schon mehrere Obfuscatoren ausprobiert, meiner Ansicht nach sind der Phoenix Protector und der Eazfuscator.NET obfuscator die beiden besten.

Wobei der Eazfuscator.NET obfuscator die Namespaces, Klassen und Methoden stärker verschlüsselt, wohingegen der Phoenix Protector meinen Disassembler öfter zum Abstürzen bringt.

Viele Grüße.

30.08.2010 - 13:25 Uhr

Hallo Herbivore,

danke für deine Informationen.
Ich habe mir das FAQ und alle verlinkten Themen durchgelesen, konnte dort aber keine Antwort auf meine Frage finden.
Wenn ich das hier richtig verstanden habe:


// Pass a logRounds parameter to GenerateSalt to explicitly specify the
// amount of resources required to check the password. The work factor
// increases exponentially, so each increment is twice as much work. If
// omitted, a default of 10 is used.
string hashed = BCrypt.HashPassword(password, BCrypt.GenerateSalt(12));

// Check the password.
bool matches = BCrypt.CheckPassword(candidate, hashed);

Wird das Passwort hier ebenfalls in einer Variable "password" gespeichert?!

Meine Frage ist nun wo ich den Klartext, den die Passwortvariable enthält am besten bzw. sichersten zuweisen kann?

29.08.2010 - 23:41 Uhr

Hallo Community,

ich möchte mein E-Mail Passwort im Code so verschlüsseln, das es beim disassemblern nicht ausgelesen werden kann.

Beim verschlüsseln Hilft mir die Klasse ProtectedData mit der Methode Protect.

Beispiel:


byte[] s_aditionalEntropy = { 9, 8, 7, 6, 5 };
System.Text.ASCIIEncoding asc = new System.Text.ASCIIEncoding();

byte[] secure = ProtectedData.Protect(asc.GetBytes("ich bin ein passwort"), s_aditionalEntropy, DataProtectionScope.CurrentUser);
System.Net.NetworkCredential nc = new System.Net.NetworkCredential("blackdynamic", asc.GetString(ProtectedData.Unprotect(secure, s_aditionalEntropy, DataProtectionScope.CurrentUser)));

Meine Frage ist nun, muss ich die Zeile (asc.GetBytes("ich bin ein passwort")) noch irgendwie so verschlüsseln, dass ich "ich bin ein passwort" in den Application Settings ablege o.ä.?
Oder kann das Passwort so schon nicht mehr beim disassemblern ausgelesen werden?

27.08.2010 - 16:45 Uhr

Hallo!

Mittels Profiler kannst du rausbekommen, wo dein Programm viel Zeit verbraucht.

Wie benutze ich so einen Profiler denn bzw. wo bekomme ich einen her?

Messen braucht man da imho nix.
Alle Vorgänge die unter bestimmten Umständen länger als 1 Sek dauern, sollten meiner Meinung ausgelagert werden (sofern es sich nicht um die GUI handelt)

wie soll ich denn ohne Messen herausfinden welcher Vorgang über eine Sekunde dauert?

27.08.2010 - 15:52 Uhr

Wo ist denn der Unterschied ob ein Thread aus dem Threadpool verwendet wird oder nicht?

Kann man irgendwie messen welche Aufgaben aufwändig sind? Kenne mich damit noch nicht so gut aus ...

27.08.2010 - 14:36 Uhr

Sorry aber ich meinte eher wo es Erfahrungsgemäß Sinn macht Threading ein zu setzen also wann es an welchen Stellen am effektivsten ist.

Ist der Backgroundworker "sauberer" als die normale Thread Klasse oder als das Invoken von Delegates?

27.08.2010 - 13:49 Uhr

Hallo Community,

ich bin dabei eine Anwendung zu entwickeln die viel zeitgleich arbeiten muss. Könnt ihr mir sagen, wie ich heraus finde an welchen Stellen einer Anwendung Threading Sinn machen würde bzw wo es erfahrungsgemäß am effektivsten ist? Habe u.a im Moment das Problem, dass meine Anwendung hin und wieder stark hängt wenn sie viel Input aufeinmal verarbeiten muss. Die Anwendung basiert nicht auf dem MVVM Pattern, weil ich zZ. noch kein gut erklärtes Tutorial dazu gefunden habe.

Und könnt ihr mir sagen welche Threading Variante am effektivsten und "saubersten" ist?
Es gibt ja mehrere Varianten des Threadings.

Viele Grüße
blacki

23.08.2010 - 14:06 Uhr

Ich habe den Fehler gefunden. Im Hintergrund war noch ein Fenster geöffnet von dem die View bereits geschlossen war, das Fenster an sich aber nicht korrekt geschlossen wurde. Danke für eure Hilfen.

Viele Grüße
Blacki

23.08.2010 - 10:32 Uhr

Vielleicht eine externe Ressource die ein Thread verwendet?

Wie könnte ich das denn heraus finden bzw. mir diese Threads ebenfalls anzeigen lassen?

An xxxprod:
Ich Rufe mein MainWindow nirgendwo explizit im c# Code auf, soweit ich weiss passiert das durch die xaml Datei.

23.08.2010 - 09:33 Uhr

Ich habe mir das Threads Menü anzeigen lassen, es zeigt keine Threads an.

23.08.2010 - 00:57 Uhr

Ja, du hast recht. Ich arbeite mit Threads.
Im Konstruktor des Hauptfensters verwende ich allerdings noch keine Threads.

Das Problem besteht jedoch auch, wenn ich die Anwendung öffne und direkt danach wieder schließe.

23.08.2010 - 00:32 Uhr

Hallo Community,

ich habe im Moment das Problem, dass sich meine Applikation nicht komplett schließt.
Wenn ich es aus VS heraus starte, und danach die Applikation oben rechts auf dem roten Kreuz schließen möchte, verschwindet zwar die View der Applikation, aber VS schaltet nicht zurück in den Bearbeitungsmodus. Das bedeutet die Applikation läuft im Hintergrund und wird anscheinend nicht vollständig beendet. Wenn ich auf "Break All" klicke, kommt die Meldung "No Source Available" "No symbols are loaded for any call stack frame. The source code cannot be displayed".

Weiss jemand von euch, woran das liegt und wie ich den Fehler beheben kann?

Viele Grüße
blacki

22.08.2010 - 20:09 Uhr

Wenn du wirklich die Standardanwendungs- bzw. -benutzereinstellungen verwendest, sind diese aus jeder Klasse heraus ansprechbar mittels.

  
Properties.Settings.Default.<DeineVariable>;  
  

Schau dir dazu die vom Studio generierte Datei Settings.Designer.cs unterhalb des Property Ordners an.

Vielen Dank.
Mit dieser Information kann ich mein Problem nun lösen.

Ich danke herbivore und Stipo, die mich überzeugt haben, nicht die die Registry zu verwenden.

esskar danke für die Hilfe, allerdings werde ich das Konfigurationsmodell verwenden.

Viele Grüße
blacki

21.08.2010 - 02:35 Uhr

Hallo herbivore,

ja das hatte ich eigentlich auch vor.

Allerdings ist bei mir z.Z. folgendes Szenario:

Die Settings werden beim laden des Startfensters geladen.
Verändert werden sie allerdings in einem extra Fenster das "Einstellungen" heisst.
Nur das Fenster "Einstellungen" soll die Settings in der Konfiguration abspeichern können.

Wenn ich nun aber die Settings, welche ich im Startfenster geladen habe, an das "Einstellungen" Fenster übergebe, um das "Einstellungen" Fenster entsprechend den momentanen Einstellungen darzustellen, bekomme ich immer den Fehler, dass die Settings weniger Zugreifbar als die Methode sind, an die ich sie übergeben möchte. Die Settings sind ja private und da die Methode von einem anderen Fenster kommt, ist sie public.

Ich könnte natürlich auch einfach alle Einstellungen in public properties zwischenspeichern und dann aus meinem Startfenster heraus aufrufen, aber ich denke, dass ist "von hinten durch den Rücken ins Auge" oder?
Ich würde mich freuen, wenn ihr mir helfen könntet, das ganze ein wenig professioneller zu lösen.

Desweiteren würde mich mal interessieren, warum die Verwendung des Konfigurationsmodells besser ist, als die Verwendung der Registry?
Das ist eine reine Interessenfrage also wenn es zu aufwendig wäre das zu erklären ist es auch kein Problem.

Viele Grüße
blacki

20.08.2010 - 23:34 Uhr

Hallo Community,

ich habe in meinem Programm eine statische "Settings" Klasse, welche alle Einstellungen beinhaltet.
Der User soll die Möglichkeit haben, diese Einstellungen zu speichern.

Da sich das Speichern von statischen Klassen in einer XML-Datei aber als ziemlich kompliziert darstellt, habe ich mir überlegt, ob ich die Einstellungen nicht am besten einfach in die Registry schreiben sollte?

Könnt ihr mir eventuell sagen, wie ich das umsetzen kann?

Viele Grüße und danke schon mal im vorraus.
blacki

19.08.2010 - 14:04 Uhr

Ups, da hatte ich mich schlichtweg verlesen.
Jetzt funktionierts.

Vielen Dank für eure Hilfe.

19.08.2010 - 13:36 Uhr

Ja, im Header sollen nur Strings stehen.

Ich habe das jetzt so eingebaut wie ihr gesagt habt:


<GridViewColumn DisplayMemberBinding="{Binding Nick}" Width="100">
<GridViewColumnHeader Content="Nickname" Horizontal Alignment="Left"/>
</GridViewColumn>

Die Schrift ist jetzt auch links allerdings ist jetzt der Hintergrund des Headers nurnoch da wo auch der Headertext ist, also habe ich nun eine weiße Lücke bis zum nächsten GridViewColumn.

19.08.2010 - 11:28 Uhr

Hallo Community,

ich habe in meine XAML-Datei ein ListView Control mit mehreren GridViewColumns eingefügt, die alle unterschiedliche Header beinhalten. Der Headertext wird über der jeweiligen Spalte zentriert angezeigt.

Kann mir jemand sagen, wie ich den Headertext linksbündig machen kann?

Viele Grüße
blacki

19.08.2010 - 11:19 Uhr

Ich wollte nur sicher sein, dass ich die Antwort richtig verstanden habe.

Vielen Dank für eure Hilfe.

19.08.2010 - 09:09 Uhr

Das bedeutet, ich muss einfach das Fenster im GUI-Thread deklarieren um es dann später im Thread wie ein Control invoken zu können und es somit im GUI-Thread zu starten?

19.08.2010 - 08:29 Uhr

Hey, mein Programm sucht etwas und wenn es was gefunden hat soll es ein neues Fenster öffnen wo dann alle Details über das Ergebnis stehen.

Was brauchst du für Informationen um mir sagen zu können wie ich das Fenster im GUI thread aufrufen kann?

Vielen Dank für deine Hilfe.

Viele Grüße

18.08.2010 - 23:47 Uhr

Hallo Community,

ich habe ein Problem und würde mich sehr freuen, wenn ihr mir weiter helfen würdet.

Ich befinde mich in einem neuen Thread und möchte von hier aus ein anderes Window aufrufen.


new OpponentFoundDialog(opponent).Show();

Dann bekomme ich allerdings folgende Fehlermeldung:

The calling thread must be STA, because many UI components require this.

Nun kenne ich das Thread Problem von anderen Controls, wo der Dispatcher die Lösung war. Also habe ich versucht, dass ganze auch auf mein Fenster anzuwenden:


                    if (!new OpponentFoundDialog(opponent).Dispatcher.CheckAccess())
                    { // Wenn Invoke nötig ist, ...
                        // dann rufen wir die Methode selbst per Invoke auf
                        new OpponentFoundDialog(opponent).Dispatcher.Invoke(new Action(() => OnQueryMessage(sender, e)));
                        return;
                    }

                    new OpponentFoundDialog(opponent).Show();

Zur Erklärung: Das "(new Action(() => OnQueryMessage(sender, e)))" wird benötigt, weil sich der Aufruf des Fensters in der Methode "OnQueryMessage" befindet, welche die Parameter "sender" und "e" fordert.

Der Fehler besteht allerdings weiterhin.
Könnt ihr mir sagen, wie ich dieses Problem lösen kann?

Viele Grüße
blacki

02.08.2010 - 22:51 Uhr

Vielen Dank das war der Entscheidende Hinweis. 😄

Ich hatte die Verlinkung wohl schonmal gesehen aber nur halb Implementiert, hatte das Dispatcher.CheckAccess() übersehen.

Liegt vielleicht an der Uhrzeit.

Ich danke euch beiden trotzdem nochmal sehr für eure hilfe, ihr scheint echt ne Klasse Community zu sein die man gut weiter empfehlen kann.

Viele Grüße

02.08.2010 - 22:08 Uhr

Vielen Dank für deine Antwort.

Sorry aber so weit sind meine C# Kenntnisse noch nicht, als das ich verstehen würde was dich da gerade so begeistert hat 😃

Mein Problem ist gerade einfach, dass ich nicht weiss wie ich die Textbox Invoken soll. Hab auch schon beim MSDN geguckt, aber bin dort auch nicht weiter gekommen.

Allerdings hab ich mittlerweile mitbekommen, dass dieses Invoke wohl eine Typische Eigenschaft von Windows Forms ist!?

Habs jetzt mal so versucht, aber da bekomme ich in der Runtime den Fehler, dass die Textbox nicht auf ISynchronizeInvoke gecastet werden kann.

        string message;

        public MainWindow()
        {
            irc.OnReadLine += new ReadLineEventHandler(OnReadLine);
            InitializeComponent();
        }

        void ReadLine()
        {
               if (((ISynchronizeInvoke)this.textBox2).InvokeRequired) { // Wenn Invoke nötig ist, ...
              // dann rufen wir die Methode selbst per Invoke auf
              textBox2.Dispatcher.Invoke (new MethodInvoker (ReadLine));
              return;
             }
                // eigentlicher Zugriff; läuft jetzt auf jeden Fall im GUI-Thread
            textBox2.Text = message;
        }

        void OnReadLine(object sender, ReadLineEventArgs e)
        {
            message = e.Line;
            ReadLine();

            if ((e.Line.ToString().StartsWith("PING")))
            {
                string server = e.Line.ToString().Split(' ')[1];
                irc.WriteLine("PONG " + server, Priority.Critical);
                Console.WriteLine("Responded to ping at {0}.",
                    DateTime.Now.ToShortTimeString());
            }
        }

bin euch nach wie vor für Hilfen sehr dankbar...

02.08.2010 - 21:27 Uhr

Also soweit versteh ich das:


        private void button2_Click(object sender, RoutedEventArgs e)
        {
            irc.Connect(server, port);
            Console.WriteLine("Connected.");
            irc.WriteLine(Rfc2812.Nick("asdassssblackdyna"), Priority.Critical);
            irc.WriteLine(Rfc2812.User("asdassssblackdyna", 0, "asdassssblackdyna"),
                Priority.Critical);
            irc.WriteLine(Rfc2812.Join(channel));
            Thread thread = new Thread(irc.Listen);
            thread.Start();
        }

Aber wie soll ich nun diese Listener Methode:


public void Listen(bool blocking)
        {
            if (blocking) {
                while(IsConnected == true) {
                    ReadLine(true);
                    //Ich denke hier sollte der Invoke passieren, allerdings wie?
                    // Ich kann doch von hier aus nicht auf Elemente des GUIs zugreifen. Der Listener befindet sich in einem komplett anderen Namespace

                    if (IsConnectionError == true) {
                        if (AutoReconnect == true) {
                            Reconnect();
                        } else {
                            Disconnect();
                        }
                    }
                }
            } else {
                while (ReadLine(false).Length > 0) {
                // loop as long as we receive messages
                }
            }
        }

Mit Hilfe dieses Beispiels hier anpassen


void DoCheapGuiAccess ()
{
   if (ctrl.InvokeRequired) { // Wenn Invoke nötig ist, ...
      // dann rufen wir die Methode selbst per Invoke auf
      ctrl.Invoke (new MethodInvoker (DoCheapGuiAccess));
      return;
   }
   // eigentlicher Zugriff; läuft jetzt auf jeden Fall im GUI-Thread
   ctrl.Text = "Hello World!";
}

Wie ist hier z.B. die Definition von ctrl?

Ich bin eigentlich davon ausgegangen, dass es sich bei ctrl um die Textbox handelt, allerdings kann ich diese nicht Invoken und auch nicht auf InvokeRequired abfragen?

02.08.2010 - 21:08 Uhr

Vielen Dank für die schnelle Antwort.

Aber ich weiss leider im Moment noch nicht wirklich wie ich das auf meine Problemstellung anwenden kann.

Was hier passiert verstehe ich soweit:
[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)

Aber in wie fern hilft mir das jetzt dabei, Events aus einem anderen Thread zu fangen?
Vielleicht hab ich einfach die wichtige Zeile im Code nicht erkannt die mir weiter helfen soll?

Es wäre nett wenn Du mir nochmal auf die Sprünge helfen würdest.