Laden...

Forenbeiträge von Tarion Ingesamt 381 Beiträge

19.02.2010 - 18:08 Uhr

<ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderThickness="3" Name="yahoo">
                        <ContentPresenter Content="{Binding}"></ContentPresenter>
                    </Border>
                    <DataTemplate.Triggers>
                        <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                            <Setter Property="BorderBrush" Value="Red" 
                            TargetName="yahoo"></Setter>
                        </Trigger>
                        <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                            <Setter Property="BorderBrush" Value="Green" 
                            TargetName="yahoo"></Setter>
                        </Trigger>
                    </DataTemplate.Triggers>
                    
                   
                </DataTemplate>
            </ItemsControl.ItemTemplate>

Dann brauche ich den ContentPresenter wieder, oder geht das auch ohne.

19.02.2010 - 14:56 Uhr

Ich bin wieder ein ganzes Stück weiter mit WPF.
Ich habe jetzt eine StudentsPage ein StudentView (UserControl) ein StudentsPageViewModel ein StudentViewModel.

Die StudentsPage soll nun die StudentViewModel rendern:


<ItemsControl Grid.Row="2" Grid.Column="1" ItemsSource="{Binding Path=Students}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ContentPresenter Content="{Binding}"></ContentPresenter>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

Dazu aus dem ViewModel an das gebunden wird:


private ObservableCollection<StudentViewModel> students;

        public ObservableCollection<StudentViewModel> Students
        {
            get
            {
                if (students == null)
                {
                    students = new ObservableCollection<StudentViewModel>();
                    students.Add(new StudentViewModel("Hans"));
                    students.Add(new StudentViewModel("Peter"));
                }
                return students;

            }
            set { students = value; }
        }

Damit das ViewModel auch gerendert wird ist natürlich noch folgendes Definiert:


<ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:FlyingClass_Wpf.ViewModel"
        xmlns:vw="clr-namespace:FlyingClass_Wpf.View">
            
            <!-- Apply a StudentView to a StudentViewModel-->
            <DataTemplate DataType="{x:Type vm:StudentViewModel}">
                <vw:StudentView />
            </DataTemplate>

            <DataTemplate DataType="{x:Type vm:StudentsPageViewModel}">
                <vw:StudentsPage />
            </DataTemplate>

        </ResourceDictionary>

Ich muss sagen, wenn man das Konzept verstanden hat ist das ziemlich cool 😃

Im Moment nutze ich in meinem DataTemplate für die Student Objekte ja ein ContentPresenter. Das geht soweit, ist aber nicht was ich möchte.
Ich will alle Students in einem Grid anordnen der 4x4 groß ist. Wenn es mehr Studenten werden, sollen die Dimensionen ggf noch Dynamisch angepasst werden können.
Ich habe da an einen UniformGrid gedacht. Die Property für die Größen, kann ich an das StudentsPageViewModel binden und dort berechnen. Je nach Größe der ObservableList.
Aber wie weise ich jedem StudentViewModel seinen Platz zu? Muss jedes StudentViewModel col und row besitzen? Wo setzte ich diese Werte dann, im StudentsPageViewModel?
Wenn ich das so mache, ist mir immer noch nicht klar, wie dann der XAML Code aussehen muss.

Wie binde ich da die Elemente des UniformGrid dynamisch an die Elemente der ObservableList? Oder eignet sich etwas anderes besser. Gibt es ne List Welche Komponenten sich zur Darstellung einer ObservableList überhaupt eignen?

P.s.
Ist es sinnvoll die DataTemplates später aus zu lagern?

Edit:
Okay ich hab viel über das ItemsControl gelesen, im prinzip kann man da ja ziemlich viel mit machen. Aber wie sage ich dem das es meine Items im n*m grid anzeigt.

18.02.2010 - 22:26 Uhr

Ein Konkretes Beispiel:

Das Model hält Daten über einen Benutzer, dieser Benutzer ist übers Netzwerk verbunden, nun kommt eine Meldung an das Model, das den Namen des Benutzers ändert. Die View hat nun den angezeigten Namen zu ändern. Muss also benachrichtigt werden. Der Netzwerkcode kennt das ViewModel nicht muss also ein Event werfen welches das ViewModel fängt.

18.02.2010 - 22:15 Uhr

Zu letzterem ein schönes Beispiel was grade bei einem Kollegen auftrat:
DataGridView mit Databinding an eine DataTable.
DataTable wurde gefüllt und Grid hat es angezeigt. Sobald die Grid "Voll" war hing die Anwendung.
Da wurde die DataTable im anderen Thread gefüllt und als der DataGridView seine Scroolbar haben wollte (von der winapi?) hats geknallt. Bis dahin ging es gut. Es geht also oft gut aber wenn nicht sind die Fehler schwer zu finden.

Wenn man einen eigenen Thread macht und dort Application.Run ist das eben der GUI Thread, sagt ja wirklich keiner das es der HauptThread sein muss, das stimmt. Aber es sollte nur einer sein 😃

18.02.2010 - 15:42 Uhr

Interessanter Thread, hat mir sehr geholfen.

1)
Ich hab aber auch noch ein paar offene Fragen.
Angenommen wir erweitern das Beispiel von oben, die View soll nicht nur Teile Foo anzeigen sondern auch noch die Werte einer Klasse "Car" um etwas anschaulicher zu werden 😉

Jetzt würde ich dem ViewModel im Konstruktor auch noch das Car mit geben und der View bereit stellen. Wenn es jetzt eine 2. View gibt welche nur Foo anzeigt aber eben diesen OK Mechanismuss nicht will, hätte ich ein weiteres ViewModel.

Damit fällt für mich die generelle Überlegung 1VM <> 1V oder 1VM<>1M raus und hängt sehr von der aktuellen Anwendung ab. Man sollte das dann jeweils entscheiden und muss selber im vornherein bedenken ob man später Lokalisieren muss oder welche Anforderungen noch folgen.

2)
Zum Datenfluß:
Es ist klar, das es wichtig ist, das die View nur das ViewModel kennt. Angenommen wir binden vom ViewModel direkt an Bar ist das natürlich erstmal unsauber aber einfach, solange Bar INotifyPropertyChanged implementiert. Änder sich das, muss man nur das ViewModel anfassen was für mich der Vorteil der Losen Bindung ist (Nur ein Teil pro Änderung anzufassen).

Von Gepro kam oft die Frage wie das ViewModel nun die Änderungen der View mit bekommt.
Klar ist: Das Model kennt das ViewModel nicht!
Der Einfachste Fall: Irgendwas ändert das ViewModel (Kann nur die View sein), dann aktualisiert diese das Model z.b. die eigenschaft Bar von Foo.
Eventuell zeigt ein anderes model aber ebenfalls diese Property an, oder es ändert die Klasse Car die Property Bar von Foo innerhalb des Models (kann auch ja sein).

Es führ nun kein Weg daran vorbei, dass die ViewModels diese änderung am Car mit bekommen müssen. Dies kann aber auf sehr unterschiedliche Weise passieren.
Das Model kann es dem ViewModel nicht direkt sagen, das ViewModel kennt aber das Model: Also muss das Model ein Event werfen (Nicht unbedingt ProperyChanged).

Hat man mal ein Model welches sich nicht überwachen lässt, kann das ViewModel im schlimmsten Fall sogar pollen. In jedem Fall sollte man einen weg nehmen der die Sichtbarkeiten nicht durchbricht.

--

Sind in meinen Ausführungen jetzt irgendwelche Groben Fehler? Ich bin auch neu in dem Gebiet.

Edit:
Ich bin hier davon ausgegangen, dass View und Model Synchron bleiben. Dieser Thread hat mir da auch noch sehr weiter geholfen:
Gundsätzliches MVVM-Verständnisproblem
Folge: Synchrone View zum Model ist eher die Ausnahme als der Regelfall. Auch wenn ich es oft selbst so implementiert hatte. Vielleicht ist der Weg mit dme Zwischenspeichern wirklich besser 😃

Gruß, Tarion

18.02.2010 - 14:43 Uhr
Frame.Navigate()
18.02.2010 - 14:02 Uhr

Naja das UserControl mit dem Codebehind verbinden hab ich ja offensichtlich gemacht.
DataContext = this ist dann natürlich noch etwas eleganter.

Ich will aber schon irgendwann beim MVVC ankommen.
Von ContentPresenter und DataTemplates hab ich bisher nur entfernt etwas gehört. Ich werde mal auf die Suche gehen. Jeder hinweis wie das im Code aussieht würd mir dennoch weiter helfen 😃

Gruß, Tarion

18.02.2010 - 00:04 Uhr

Meine WPF Kenntnisse nehmen Fomen an. Die Gundelemente hab ich schon ganz gut im Griff, jetzt kommen die Daten zu Anzeige.

Ich habe UserControl was einen Schüler anzeigt. Der Schüler ist ein "Student" objekt.

Das UserControl heißt StudentView.

Mein Ansatz:
Das StudentView bekommt die Property Student und bindet diese.


public Student Student
        {
            get { return student; }
            set 
            { 
                student = value;
                this.Resources["Student"] = value;
            }
        }



<Grid DataContext="{DynamicResource Student}">
...
<Label Content="{Binding Name}" Name="lblName" Grid.Row="1" Grid.ColumnSpan="2" VerticalContentAlignment="Center" HorizontalContentAlignment="Center">
...
</Grid>

Die Fragen: Kann ich eleganter an eine Property des UserContols binden? Ohne Ressources oder DataContext zu nutzen?
Wenn ich nur an ein Objekt binde wie in meinem Fall wäre die DataContext property wohl der direktere weg, aber vom Codeaufwand muss ich in der Property dann eben den DataContext statt die Resource ändern.

Oder ist meine Lösung so schon best Practice?

Edit: Hab noch was von Dependency Properties gehört aber noch nicht komplett verstanden, wäre dies ein Anwendungsgebiet für eine? Beispielcode wäre dann super.

Danke und Gruß, Tarion

15.02.2010 - 21:21 Uhr

Ich beschäftige mich grade zum ersten mal ernsthafter mit WPF, und es hat schon eine Stunde gedauert ein UserControl in mein Hauptfenster ein zu binden.
Gibt es irgendwo gute Tutorials zu WPF? Ich hab schon bisschen gesucht aber so richtig Praxisnah und gut war noch nichts.

Ich bräuchte auch Erklärungen zu den neuen Controls und deren Möglichkeiten.

Aktuelles Problem ist in einem UniformGrid dynamisch Controls hinzu zu fügen.
Zumindest ist das mein Intuitiver Ansatz wenn ich bis zu 16 Bilder in einem quadratischen Gitter darstellen will. Die Bilder werden nach und nach geladen und sind nicht statisch.

15.02.2010 - 00:01 Uhr

Was heißt simulieren?
Willst du das gleiche Interface haben wie du es für Dateien hast? Dann ist es im prinzip ein Stream, ob nun FileStream oder MemoryStream oder sogar ein Networkstream gibt sich nicht viel. HAuptunterschied sind die auftretenden Fehler.
Netzwerverbindung, Dateirechte, .. MemoryStream dürfte fast immer gehen.
Wenn du auch auftretende Fehler Simulieren willst kannst du den MemoryStream ja noch in einer Klasse kapseln die sich als Datei ausgibt und ggf Exceptions wirft wie ein Dateisystem.

14.02.2010 - 23:53 Uhr

Siehe: [FAQ] Warum blockiert mein GUI?
Die Frage kommt oft in diversen Varianten.

Generell: Gui im Gui thread: Apllication.Run(new MyForm());
Dann alles andere in eigene Threads auslagern und zur GUI synchronisieren. Nicht die GUI in eigenen threads erstellen, das funktioniert nicht.

Für die Progressbar auch immer gut: BackgroundWorker

13.02.2010 - 12:50 Uhr

Im Debug menu gibt es eine Möglichkeit einzustellen, bei welcher Exception der Debugger anhält. Vielleicht sind da die Standardoptionen anders.

10.02.2010 - 22:03 Uhr

Hi,
ich will immer lieber mal mit WPF anfangen. Jedoch ist wie ich auch schon aus verschiedenen Quellen gehört habe der Designer in VS nicht besonders toll. Nun die Frage, ist der Designer ausreichend um damit ohne deutlich mehr Aufwand die gleichen Dinge umzusetzen wie mit WinForms?
Oder lohnt es auch mit dem VS Designer auf WPF zu setzten.

Ein anderer Punkt ist die Einarbeitungszeit die aber ohnehin anfällt. Ich hätte auch noch Expression Blend zur Verfügung, aber das kann wieder so viel das ich da in jedem Fall noch mal das Doppelte an Einarbeitung rauflegen kann.
Wobei sich dann die Frage stellt: Wenn WPF, dann gleich mit Blend oder lieber erstmal mit dem Designer anfangen.

Gruß, Tarion.

10.02.2010 - 21:55 Uhr

Statt die Forms im eigenen Thread zu erstellen, solltest du also lieber alles was wirklich Zeit frisst (Initialisierung von Daten, IO, ...) in einen extra Thread auslagern und dann zurück zur GUI synchronisieren. Wenn die Form zu lange zum laden braucht hilft es auch nichts sie in einen Thread aus zu lagern, denn das was man sieht ist ja nunmal die GUI und die bleibt immer gleich langsam wenn deren Aufbau durch andere Operationen geblockt wird.

10.02.2010 - 16:29 Uhr

am besten du fängst beim command pattern an. generell ist es extrem schwer solche features im nachhinein in eine anwendung einzupflegen. sowas macht man eigendlich als eines der ersten sachen...

Tja, da kann ich leider zustimmen, nachdem ich mich mal für einen iterator entschieden habe der nur vorwärts gehen kann und ich dann auch die zurück Funktion implementieren sollte. Die Lösung im nachhinein war ziemlich Zeitaufwändig (und noch nicht ganz fertig^^)

Ich habe mir Context objekte gebau in denen der gesammte Zustand gespeichert ist und über welche die Interaktionen laufen (auch ne art Commands mit größerem Interface)
Diese werden in einer List verwaltet und können dann den aktuellen Zustand schnell ersetzten wenn man zurück geht.

05.02.2010 - 14:55 Uhr

Gut, ich muss der Gruppe zum Empfangen nicht beitreten, aber wenn der PC senden will, kommt die gleiche Exception.

05.02.2010 - 14:45 Uhr

SocketException: Der Host war bei einem Socketvorgang nicht erreichbar

Tritt auf bei:


private void ReceiveBroadcast()
        {
            using (Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
            {
                IPEndPoint iep = new IPEndPoint(IPAddress.Any, broadcastPort);
                sock.Bind(iep);
                
                IPAddress multicastGroup = IPAddress.Parse("224.0.0.1");
                sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastGroup, IPAddress.Any)); // Hier wird die Exception geworfen

                EndPoint ep = (EndPoint)iep;

                while (clientRunning)
                {
                    if (sock.Available > 0)
                    {
                        byte[] data = new byte[1024];
                        int recv = sock.ReceiveFrom(data, ref ep);

                        BroadcastPacket packet = PacketHelper.DeserializeStruct<BroadcastPacket>(data);
                        ThreadSaveEvent.InvokeEventSave(BroadcastReceived, this, new BroadcastEventArgs(packet));
                    }
                    Thread.Sleep(100);
                }

                sock.Close();
            }
        }

Auffällig ist das sock.Available nen Wert von > 2000 hat wenn die Exception fällt.

Edit: mit ner anderen multivast IP geht es auch. Das hilt mir nur nich viel weiter? Wie löse ich die ursache der Exception?

Woran kann diese Exception liegen?

05.02.2010 - 11:27 Uhr

Alles was ordentlich läuft ist kein Problem. Ich will merken wenn das W-Lan weg ist oder der Stecker gezogen wurde.

Funktioniert mein Code noch wenn ich byte[] tmp = new byte[0]; sende und die 0 lasse?

04.02.2010 - 23:39 Uhr

Ich such nochmal in der socketklasse nach Timeouts, im moment stellt das Programm erst nach mehreren Sekunden den Disconnect fest. Das müsste doch irgendwie schneller gehen.

04.02.2010 - 14:50 Uhr

Eine recht einfache Funktion die einen Multicast sendet:

private void SendMulticast(byte[] data, IPAddress ip, int port, int ttl)
        {
            using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
            {
                IPEndPoint ipep = new IPEndPoint(ip, port);

                socket.Connect(ipep); // Hier tritt die Exception auf

                socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ipep.Address));
                socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, ttl);

                socket.SendTo(data, ipep);

                socket.Close();
            }
        }

Der Fehler:

04.02.2010 14:35:36 <4> Error: Can't send multicast form IP: 192.168.196.1 - Der Host war bei einem Socketvorgang nicht erreichbar 224.0.0.1:4752

Die Ursache:
socket.Connect(ipep); soll ja nur eine einfache UDP Verbindung über den Netzwerkadatper erzeugen. Das funktioniert so lange, bis ich mit meinem pc den VPNClient einmal gestartet hab um in user Uni netz zu kommen. Wenn ich dann in einem anderen Netzwerk bin, wird diese Fehlermeldung geschmissen. Offensichtlich wird ein falscher Adapter (Der nicht verbundene vom VPN?) verwendet. Internet geht aber.
Ein Neustart des Rechners hilft, aber soll ja nicht die Lösung sein.

Die Frage:
Wie kann ich im Programm festlegen welcher adaper (oder halt nacheinander alle Adapter) genutzt wird?

04.02.2010 - 08:07 Uhr

Die GUI Elementen können auch im OnValidate oder onKeyPress oder wann auch immer es nötig ist die Validierung durchführen. Wenn du den Code nicht in der GUI haben willst schau dir Dependence Injection an.

03.02.2010 - 13:08 Uhr

Gibt es eine saubere Lösung schnell zu detektieren ob eine TCP-Verbindung noch besteht.
Kann ich etwas senden und auf ACK warten ohne das die andere Seite auf Anwendungsebene Daten bekommt? Wie hoch sind die Timeouts für die TCP Verbindung fürs ACK oder wo stelle ich die ein.

Ich hab auch schon was gecoded, aber das kommt mir nicht sehr zuverlässig / schnell vor:


 bool blockingState = tcpClient.Client.Blocking;
            try
            {
                byte[] tmp = new byte[1];
                tcpClient.Client.
                tcpClient.Client.Blocking = false;
                tcpClient.Client.Send(tmp, 0, SocketFlags.None);
                // Connected!
            }
            catch (SocketException e)
            {
                // 10035 == WSAEWOULDBLOCK
                if (e.NativeErrorCode.Equals(10035))
                {
                    Logger.Log("Poll: Still Connected, but the Send block", LogLevel.Warning);
                }
                else
                {
                    Logger.Log(String.Format("Poll: Disconnect detected: error code {0}!", e.NativeErrorCode), LogLevel.Info);
                    InvokeDisconnect();
                }
            }
            finally
            {
                tcpClient.Client.Blocking = blockingState;
            }

02.02.2010 - 22:38 Uhr

Statt des "txbZahl1.Text != null" solltest du besser "!String.IsNullOrEmpty(txbZahl1.Text)" schreiben - dann zählen auch leere Strings - null ist der Text einer TextBox IMHO eher selten.

Laut MS ist

txbZahl1.Text.Length > 0

das beste 😃

02.02.2010 - 22:31 Uhr

Nutze den Debugger, setze Breakpoints vor die Exception und überprüfe wie groß das Array ist auf das zugegriffen wird wenn die Exception fällt. Dann sollte auch klar werden welches array wieso zu klein ist.

Spalten Ausblenden geht meiner Efahrung nach auf 2 Arten gut:

  1. AutoGenerateColumns = false
    Damit musst du alle Spalten selbst anlegen, nutzt du DataBindings, hilft der Deigner dabei sehr gut.
  2. Ebenfalls mit Databindings der Datenquelle über ein Attribut sagen, das entsprechendes Element nicht angezeigt wird. Würde dann aber in keinem Grid erscheinen und ist oft nicht gewollt.

Und auf eine Art nicht so gut:
3. In irgend nem Event die Column wie du es probierst auf Visible = false setzten. Ich glaub ich hatte es im ColumnAdded event. Da kannst du abfragen welche wie der Spaltenname der neuen Spalte ist und wenn es die unsichtbare ist gleich die Property setzten. Aber das hat bei mir teilweise gebuggt, was aber wohl auch an den Databindings lag die ich dennoch verwendet hatte.

Gruß, Tarion

02.02.2010 - 22:25 Uhr

Ich würde innerhalb eines TLP wirklich ein UserControl vorziehen. Oder hat es besondere Gründe, wesshalb du unbedingt Forms benötigst?

02.02.2010 - 18:26 Uhr

Hi,
ich suche eine Möglichkeit den gesamten Traffic der durchs Netzwerk geht mit meinem Programm zu verwalten. Dafür können ruhig Windowskonfigurationen nötig sein.

Ich habe an etwas wie einen Netzwerkadapter gedacht, welcher allen Traffic an mein Programm weiter leitet. Jedoch kenne ich mich da nicht gut aus wie und ob das möglich ist.

Wenn ich damit erstmal allen Traffic der Raus geht loggen kann wäre das super.
Weiterhin soll mein Programm aber auch eine TCP Verbindung nach draußen (Internet) aufbauen können. Das wäre dann der 2. Schritt.

Hoffe mir kann jemand helfen oder sagen wieso es zum scheitern verurteilt ist.

Gruß, Tarion

27.01.2010 - 18:30 Uhr

Was meinst du mit Busy waiting?

im sinne von polling. polling ist imer schlecht und auch in diesem fall nciht notwendig.

Aber wenn ich die Abfrage weg lasse, hängt er im Receive. Dann kann ich den Thread nicht beenden. Zumindest hab ich es nie richtig hin bekommen. Ne Lösung dafür würde mich interessieren.

Und wgen den Threads hab ich ja nur eine limitierte Anzahl, die man bei bedarf auch auf 1 stellen kann.

Gruß, Tarion

27.01.2010 - 15:10 Uhr
  1. du musst nicht manuell prüfen ob das objekt disposed ist und dann eine ObjectDisposedException schmeissen. das macht das framework auch so für dich.

Im folgenden Beispiel gibt es keine Exception. Oder was genau meinst du übernimmt das Framework.


Disp myDisposable = new Disp();
myDisposable.Dispose();
myDisposable.Dispose();
myDisposable.Foo();

// Mit dieser Klasse:
public class Disp : IDisposable
    {
        int x;
        public void Foo()
        {
            x++;
        }

        #region IDisposable Members

        public void Dispose()
        {
            Console.WriteLine("Dispose Test");
        }

        #endregion
    }



  1. bei UDP kenne ich es so, das generell alles 4-6 mal im stil von fire&forget gesendet wird. hintergrund ist der, das packete im allgemeinen öfters verloren gehen können, als es den meisten bewusst ist. eine option hierfür wäre zumindest von vorteil, da bei mehrmaligen aufrufen von außen je jedesmal neue sockets erstellt werden.

Jedes mal x Packets senden ist schnell implementiert. Werde ich einabuen.

  1. verwende das using {...} um sicherzustellen, das objekte auch beim auftreten von exceptions disposed werden. z.b. sockets.

Stimmt.

  1. verwende lieber den threadpool anstatt in einer liste manuell threads zu erstellen.

Ich habe x Threads welche die ganze Zeit arbeiten.
Ich würde permanent einen Thread pro Verbindung aus dem Threadpool nutzen und wenn der Pool leer ist kann ein Client nicht behandelt werden. Das kann mir mit meinen 10 Threads die auf einer Queue arbeiten nicht passieren. Eventuell reicht 1 Thread. Aber mehrere Tthreads können bei Komplexen Geschichten die Antwortzeiten erhöhen. Auch kann ein Thread mal hängen bleiben und die anderen arbeiten auf allen anderen Clients weiter.
Für Berechnungen und zeitlich begrenztere Aufgaben stimme ich dir zu. Hier sehe ich den Vorteil vom Threadpool so noch nicht.

  1. der networklistener hat busy-waiting implementiert. das ist nciht gut. das solltest du überdenken.

Was meinst du mit Busy waiting?


`private void AcceptThread()
        {
            while (accepting)
            {
                if (listener.Pending())
                {
                    TcpClient client = listener.AcceptTcpClient();
                    clients.Enqueue(client);
                    ThreadSaveEvent.InvokeEventSave(ClientConntected, this);
                }
                Thread.Sleep(100);
            }
            listener.Stop();
        }

Geht das besser? Oder meinst du was anderes.

26.01.2010 - 23:37 Uhr

Beschreibung:

Broadcast_example ist ein kleines Projekt, welches während der Entwicklung eines größeren Programms mit entstanden ist.

Im Prinzip ist es ein vollständiges Netzwerkframework. Broadcast und Multicast (über UDP) kann vom Server verwendet werden um den Clients die IP und den Port der TCP Verbindung mit zu teilen. Die Clients können sich dann zum Server verbinden ohne Konfiguriert zu werden.

Außerdem ist eine Serialisierung / Deserialisierung für Structs enthalten und sogar der Code für eine Komprimierung der Daten, welcher zur Zeit aber nicht genutzt wird. Kann jeder selber leicht einbauen.
Später soll der Netzwerkstream automatisch in die Structs verwandelt werden und ein Event für jedes Packet geworfen werden. Das habe ich für Klassen bereits implementiert aber nicht mit in diesem Projekt.
Es wird aber bereits in allen Assemblies nach Implementationen von IPacket gesucht womit jedes Paket dynamisch eine eindeutige ID bekommt. Später muss dem Netzwerkstream dann noch die Information über Paketlänge und Paket id hinzugefügt werden damit der NetworkMessageHandler die Pakete als Structs generieren kann.
Auch mit den ID's muss noch sichergestellt werden das die Pakete immer die selben ID's bekommen. Vielleicht muss die ID doch noch eine Property oder ein Attribut der Paket Structs werden.

Funktioniert nur im LAN! Im Internet werden keine Broadcasts / Multicasts geroutet.
Nicht alle Router unterstützen Broadcast und Multicast. Mit dem Tool kann man das schnell bei seinem eigenen Router testen.

Es kann:*Client: Broadcasts / Multicasts in einer MulticastGroup und einem Port empfangen *Client: Automatisch zu einem Server verbinden, welcher den BC / MC gesendet hat *Server: Broadcast an eine IP Senden *Server: Multicast in eine MulticastGroup senden *Server: TC Verbindungen annehmen. (Bisher nur Port 1337)

TODO:* Serverport für TCP Verbindungen änderbar

  • PacketHandler fertig stellen: Networkstream in Structs parsen und Events werfen
  • Auslagerung in eine DLL

Der Quellcode ist teilweise Dokumentiert. Fragen beantworte ich gerne.
Auch Kritik und Verbesserungsvorschläge sind willkommen.

Schlagwörter: Broadcast, Multicast, TCP, Server, Client, Netzwerk, Network

26.01.2010 - 01:05 Uhr

Demnacht wird ohne Angabe eines Seeds die Uhrzeit als Seed benutzt? Ansonsten ist das immer eine gute Möglichkeit jedes mal einen anderen Sees zu haben. DateTime.Now.Ticks o.ä. als Seed zu nehmen. Einmal pro Programmstart reicht.

Pseudorandom Funktionen sollten dann das wichtigste Kriterium erfüllen: Sie sind gleich verteilt. Die Normalverteilung kann man dann noch umformen in eine beliebige andere Verteilung durch Multiplikation mit gewünschter Zielfunktion. Aber das ist für dich wahrscheinlich nicht nötig 😉

26.01.2010 - 00:42 Uhr

Bau dir z.B. ne Helferklasse die in der View genutzt wird in die du den Typ reinwirfst und dann sauber auf die Attribute zugreifen kannst.

25.01.2010 - 16:32 Uhr

Sendest nur nur nötige Teile des Bilschirminhaltes zur Aktualisierung?
Mich würde der Quellcode sehr interessieren, da ich selbst grad an eine Möglichkeit arbeite andere Rechner fern zu steuern.

20.01.2010 - 20:42 Uhr

Hab grade das hier gefunden, weil ich auch danach gesucht habe meine BindingList sortierbar zu machen. Klappt gut:

http://dotnet-snippets.de/dns/c-bindinglist-mit-sortierfunktion-SID1129.aspx

19.01.2010 - 15:25 Uhr

Hi,

Tarion wollte aber speziell nur IPv4 Adressen filtern.
Außerdem fängt er noch den Fehlerfall ab, dass gerade keine IP zugewiesen (oder ausschließlich IPv6)

Man kann es natürlich troztdem in eine Anweisung qeutschen:

IPAdress ip = Dns.GetHostEntry(Dns.GetHostName()).AddressList. FirstOrDefault(  
                     ip => (ip.AddressFamily == AddressFamily.InterNetwork)  
                     ) ?? IPAddress.None;  
  

beste Grüße
zommi

Nice, aber ich habe nicht so einen starken Drang alles in eine Zeile zu bekommen 😉

16.01.2010 - 19:50 Uhr

Hab mit DataBindings zu viele schlechte Erfahrungen bei spezielleren Anwendungen. Z.B. nem TreeView. Also ich habe entweder DataBindings oder eigene Synchronisation im nötigen Rahmen zwischen der GUI und den Objekten welche die Daten enthalten. Eben diese Datenobjekte sind bei mir dann Bussiniss Objekte / Objekte des Models

Vielleicht hab ich da noch Begriffe nicht richtig Benutzt.

Im wesentlichen habe ich einen Controller der die Applikation startet und lenkt. Dort werden alle Controls und Forms erstellt und über Interfaces / Propertys / DI verheiratet. Außerdem bekommt von dort die GUI ihre Objekte aus dem Model welche dort ja dargestellt werden sollen.

Wenn ich meine Controls nun so baue, das ich die Daten über Propertys übergebe, muss ich zum einen darauf achten diese notwendigen Properties auch zu setzen. Zum anderen muss das Control auch damit rechnen das sich die Property ein 2. mal ändert.
Diese "Probleme" (Eigentlich ist es nicht wirklich schlimm...) hat man bei der Übergabe an den Konstruktor nicht, dafür aber öfter Probleme mit dem Designer (Finde ich deutlich schlimmer)

@herbivore: Das klingt vernünftig 😃

16.01.2010 - 19:37 Uhr

Habs als Control und mit OnPaint.
Das von DevExpress ist kein Balken der von der Mitte aus nach Links oder rechts gezogen werden kann. Es soll noch je nach Seite ne andere Farbe haben und eventuell will ich den Wert noch auf den Balken schrieben (Hab extreme Platzprobleme). Das Spricht alles für selber machen 😃

Hab auch viel über Controls bauen gelesen. Denke das ist so das beste.
Danke

16.01.2010 - 19:33 Uhr

Wenn die Eigenschaften sich nicht zu sehr unterscheiden, oder nicht zu viele Gruppen bilden, lassen sich die Gruppen in eigene objekte fassen.


Person p = new Person();

class Person {
	General General {get; set;} // Name, Alter, Geschlecht etc...
	Appearance Appearance {get; set;} // Augenfarbe, Hautfarbe, ...
	Communication Communication {get; set;} // Retohrik, Wortschatz, etc..
	SocialNetwork Social {get; set;} // Freunde, Familie, ...
	// Irgendwas für die Körperlichen Attribute wie Stärke, Geschick, etc..
	
}

Dann sind das schon nurnoch ~ 20 - 80 Attribute je Klasse.

Dann ist noch die Frage wie sehr die Attribute voneinander abhängen.
Wenn es nur wenige Datentypen sind wie String, Int, Double. Kann man halt noch wie oben schon gesagt einfach mehrere Dictionarys machen.


Person p;
p.GetStrAttribute("Name");

Finde ich aber nicht so schön. Oder man nimmt als Keys vom Dictionary nen enum mit den 300 Attributen. Wäre schon hübscher.

15.01.2010 - 00:34 Uhr

Mit dem Model meine ich die Daten die angezeigt werden.
Wie läuft bei dir da die Kommunikation?

14.01.2010 - 22:45 Uhr

Moin,
ich habe früher mal die nötigen Daten für ein UserControl per Konstuktor übergeben, hatte aber dann oft Probleme mit dem Designer, da man die Dinger ja doch oft per Designer platziert und nicht im Code generiert.

Seit dem habe ich immer eine Property die dann Control weit eine UpdateMethode auslöst wenn sie gesetzt und entfernt wird. Oft brauchen meine UserControls halt größere Teile vom Daten Model.

Ich wollt einfach mal hören wie ihr UserControls in der Praxis so benutzt.
Wieviel ihr mit dem Designer baut und wie viel im Code, ob der Konstuktor schon Werte bekommt etc...

Eine tolle Sache ist auch oft:


if (!this.DesignMode) {
// ...
}

14.01.2010 - 22:41 Uhr

a)
Bei FixedSingle sieht der Rahmen bei mir genau so aus wie bei FixedToolWindow

b)
Ich hatte mal bei Code Project was um eigene Buttons in die Statusleiste zu malen, damit müsste das gehen. Musst du allerdings nochmal suchen gehen. Dann kannst deinen eigene minimize button machen.

Es ist auch Betriebsystem abhängig wie der Rahmen aussieht (Ich hab jetzt Win98 Style).
Vll kannst du mal Screens zur Veranschaulichung rein stellen was genau du meinst. Aber ich fürchte ein Teil wird wirklich vom BS gemalt und kann somit dann auch nicht "übermalt" werden.

14.01.2010 - 22:21 Uhr

Recht simplel: Weil der Kunde eine andere will

Edit, etwas hintergrund:
Es ist eine Saaty skala mit der 2 Kriterien mit einander verglichen werden. Man soll einen Balken zu dem jeweiligen Kriterium ziehen können (Links <-> Rechts) und somit "aus dem Bauch herraus" entscheiden welches wie viel wichtiger ist als das andere.

14.01.2010 - 15:01 Uhr

Hi,
ich bin grade dabei ein eigenen Slider zu implementieren. Es ist ein einfaches grafisches Control mit einem Balken den man von der mitte aus in nach links oder rechts ziehen kann und werte zwischen -9 und 9 einstellt.

Die Frage ist jetzt ob es Nachteile hat das als UserControl zu implementieren oder welche Vorteile es hat ein Panel oder nur ein Control zu erben.

12.01.2010 - 18:46 Uhr

Du wirst viel selber malen müssen.

PictureBoxen sind wohl recht langsam. Man kann auch einfach ein Panel nehmen und auf dem Hintergrund malen.

Also erstmal ein Panel ableiten


public class Spielfeld : Panel 
{
// ...
}

Nun kannst du dort die OnPaint methode überschreiben. Die stellt ein Graphic objekt zur Verfügung (Im eventArg?) mit dem du mal testweise Kreise und Viewecke zeichnen kannst.

Nun ist es sehr aufwändig immer alles in einer Methode zu malen und den Überblick zu behalten wie und wo später noch Klicks aus zu werten sind.
Dafür kannst du dir einige Klassen bauen aus denen du dein Spielfeld in der "OnPaint()" Methode zusammen baust.

Das Spielfeld kann z.B. aus "Spielbrett Feldern" bestehen die jeweils X und Y Koordinaten, Width, Height und eine eigene Paint methode haben (übergebe der Paint methode der Spielbrett Felder dann das Graphic objekt damit die sich darin malen können)

Wenn du dir jetzt alle Felder erzeugst und die in eine Liste speicherst, dann in der OnPaint() Methode die Liste aller Felder durchgehst und dort jeweils Paint(Graphic g) aufrufst, dürfte dein Spielfeld schon mal ganz hübsch gemalt sein und du kannst später noch bei ankommenden Mausklicks raussuchen in welches Feld nun geklickt wurde (In der Liste der Felder suchen).

Naja und dann geht es weiter... ein ganzes Tutorial wäre wohl zu viel. Aber das sind meine Ersten Gedanken zur Realisierung.

12.01.2010 - 18:37 Uhr

es gäbe auch die Möglichkeit, dafür ein oder mehrere eigene Attribute zu implementieren.

Ja ich finde auch das es stark nach Attributes klingt.

12.01.2010 - 18:36 Uhr

Desshalb würd ich ich dem Tag keinen String sondern eine eigene Klasse z.B. "MYButtonTag" geben.

12.01.2010 - 18:18 Uhr

Die Convert methoden ins Interface zu packen würde bedeuten, dass das Interface alle seine Implementierungen kennt.

Ich würde daher die Convertierungsmethoden wohl wirklich in einer eigenen Klasse lassen.

12.01.2010 - 18:01 Uhr

Es gibt nen Serveremulator für Ultima Online (RunUO) in c#. Der Kompiliert bei Starten die Scripte zu einer dll und bindet die so ein. Änderungen an den Scripten Erfordern dann immer einen Neustart.

Zur Laufzeit was nachkompilieren ist gut möglich. Aber zur Laufzeit ersetzten?
Ich kann mir Module vorstellen die man vor dem Ersetzten sperren kann um sie dann neu zu linken und wieder zu entsperren. Eine solche Modularität bringt in der Entwicklung aber auch viele Nachteile wie Abhängigkeiten.

In Prinzip aber gerade für Serveranwendungen ne interessante Idee.

10.01.2010 - 22:55 Uhr

Okay, mich hatten die vielen Einträge in dem AddressFamily enum irritiert 😃
Hier die Lösung:

private IPAddress GetIP() {
            IPAddress resultIp = IPAddress.None;
            
            // Get the hostname
            string myHost = Dns.GetHostName();

            // Get the IP from the host name
            IPHostEntry hostEntry = Dns.GetHostEntry(myHost);

            foreach (IPAddress ip in hostEntry.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    resultIp = ip;
                    break;
                }
            }

            return resultIp;
        }
10.01.2010 - 22:46 Uhr

Ich kann die eigene IP rausfinden. Aber wie erkenne ich ob es eine IPv4 adresse ist=

Ich hab das jetzt erstmal so gelößt:

private IPAddress GetIP() {
            IPAddress ip = IPAddress.None;
            
            // Get the hostname
            string myHost = Dns.GetHostName();

            // Get the IP from the host name
            IPHostEntry hostEntry = Dns.GetHostEntry(myHost);
            for (int i = 0; i < hostEntry.AddressList.Length; i++)
            {
                string strIp = hostEntry.AddressList[i].ToString();

                if (strIp.Length <= 15)
                {
                    ip = hostEntry.AddressList[i];
                    break;
                }
            }

            return ip;
        }

Geht das nicht schöner?

10.01.2010 - 22:31 Uhr

Bin auch gerade am Basteln.
Ich hab nen Server und nen Client.
Der Server sendet Broadcasts mit seiner IP und dem Port. Der Client wartet auf einen Broadcast und wenn er einen empfängt connected er zu der IP und dem Port via TCP.

Da wird für den Broadcast auch schon gesendet und empfangen. Vielleicht hilft dir das.

Problem:
Es geht:
PC als Server -> Laptop als Client
Es geht nicht:
PC als Client -> Laptop als Server

Liegt irgendwie am Encoding des Stings im BoradCastPacket. Dazu wollte ich grade nen Thread auf machen. Aber denke der Code hilft dir auch so schon.

Edit: Ich glaub mein Laptop schickt die IPv6 IPAdresse an den PC und damit kann der nicht connecten.