Laden...
Avatar #avatar-1597.jpg
nitronic myCSharp.de - Member
Software Architect / Program Manager Österreich Dabei seit 14.03.2004 354 Beiträge
Benutzerbeschreibung

Forenbeiträge von nitronic Ingesamt 354 Beiträge

10.07.2008 - 08:51 Uhr

Die Blauäugigkeit habe ich beim letzten Mal noch überlesen. Ich bin also gleich mehrfach blauäugig weil ich das Recht nicht 100%ig auswendig kenne und Vermutungen anstelle. Zudem war dein Beispiel mit den Bildern im letzten Post unpassend (solche Copyright-Verstöße sollten nummermehr jedem bekannt sein). Und das mit dem URL-Grabber ist eher der Apfel-Birnenvergleich (ganzer Seitenklau, keine Hinweise).

Gut, wenn Copyright-Verstöße bezgl. Grafiken bekannt sind: Was unterscheidet dies von Dokumenten? 😉

@Url-Grabber: Nein, ist kein Apfel-Birnenvergleich: Gegrabbed wird inklusive Copyright-Vermerke. D.h. Name, Impressum, alles vorhanden. Der Name des Urhebers wird also ausgewiesen. Nur ists eben nicht sein Webspace.

Bist du dir da sicher? Eine der ehemalig größten deutschen Internetseiten musste Anfang dieses Jahrtausend trotz eines Relaunches schließen (der Name ist mir aber momentan entfallen). Auch sicher keine Unbekannte war das k-Hardware-Netzwerk, welches trotz vielen Besuchern schließen musste. Das Web ist immer noch schnelllebig. Da sind kleinere Seiten i.d.R. sicherer. Zwar zugegebenermaßen nicht auf den neuesten Stand, aber man kann davon ausgehen, dass der Inhalt noch einige Zeit geben wird. Beispiele, welche Seiten bis ins Jahr 199x reichen, kann ich dir gerne geben. Kleine Seiten (wie die meinige) stellen zu den großen Anlaufpunkten des Webs eine Ergänzung dar. Ich finde auch an dieser Stelle trifft dein Tonfall einen leicht überheblichen Beigeschmack. Eine kleine Rücksalve Bläuaugigkeit.

Es gibt unterschiedlichste Gründe, warum Websites schließen. Diese können privater, rechtlicher und/oder wirtschaftlicher Natur sein. Dass damit Content verschwindet ist klar.

Auf der anderen Seite wird eben Content bewußt aus dem Internet genommen. Wie auch schon gesagt wurde: Weil veraltet, weil nicht besonders gut und keine Zeit zur Überarbeitung usw. Damit musst du nun einmal leben.

@Überheblichkeit: Es ist immer eine Sache, wie etwas gesagt wird und wie es ankommt. Nicht immer ist der Sender schuld, nicht immer der Empfänger. Wenn du manches als Überheblichkeit einstufst ist das dein gutes Recht. Meines ist zu sagen, dass mir das egal ist 🙂

Ich gehe mal davon aus, dass du ein Backup nicht gestattest.

Korrekt.

07.07.2008 - 08:17 Uhr

Wiegesagt, konnte ich die Quelle nach solanger Zeit nicht mehr auffinden. Dazu unten mehr. Den Inhalt habe ich natürlich in keinster Weise verändert, wenn auch die Form darunter geleidet hat.

Das ändert an der Sachlage nichts.

Der augenscheinliche Gedanke war nur, das niemand zu Schaden käme und alle profitieren: Der private Homepagebesitzer kann Material zur Verfügung stellen; der Urheber wird über seine Grenzen bekannt; die Nutzer finden die Infos an verschiedenen Infos.
Ich meine, warum sollte der Urheber sonst seine Werke frei ins Internet stellen (meist hat keine Homepage)? Da ist eine Vervielfältigung doch erwünscht. Aber du hast die Antworten ja oben schon gegeben.

Eine Vervielfältigung ist dann erwünscht, wenn dies ausdrücklich erwähnt wird. Ausserdem stellt jemand seinen Content ins Internet, damit dieser verlinkt und nicht an anderer Stelle erneut angeboten wird. Schließlich möchte ich als Urheber mehr Traffic generieren. Möchte ich es beispielsweise nicht auf meiner eigenen Website publizieren, sondern an anderer Stelle, dann suche ich mir etwas mit großer Reputation. Siehe codeproject.com o.ä.

Was das Thema "über die Grenzen hinweg bekannt werden" angeht: Wo sei gesagt, dass dies mit deiner Website so ist? Weder kennt man Klickraten, noch sonstige weiterführende Informationen. Dein Gedanke selbst mag gut gemeint sein, entspricht aber weder der rechtlichen Grundlage, noch dem Willen der meisten Urheber.

Ich habe mal eben spontan "norbert eder gdi" eingegeben... du hast Recht. Das scheine ich übersehen zu haben?! Ich kann dir aber versichern, dass das nicht absichtlich passiert ist. Das überrascht mich insofern selbst.

Ich unterstelle dir keine Absichtlichkeit, sondern Blauäugigkeit.

Da gab es das Problem, dass z.T. die Quellen nicht mehr existierten und da wollte ich mir etwas Arbeit ersparen mit mühseligen, oft vergeblicher Mikrosuchen. Zu zweiten Punkt ist noch zu beachten, wielange man auf eine Antwort warten darf? Manchmal bekomme ich überhaupt keine Antwort (über 2 Wochen), ob es dann verpönt ist, das Material online zu stellen? Das wäre wirklich schade!

Wenn du keine Antwort erhältst, dann ist das gleichzusetzen mit einer Absage. Dies bedeutet für dich, dass du diesen Content nicht verwenden darfst.

Letztendlich habe ich drüber nachgedacht, und meine mich erinnern zu können, deine GDI-Tipps aus einem Forumthread in die Txt-Datei kopiert zu haben.
Es gibt wohl ein entscheidendes Motiv, was mich dazu veranlasst, Daten nochmal selbst anzubieten:

Wie gesagt, ich habe meinen Artikel in einer der vorherigen Posts verlinkt. Da siehst
du ganz genau woher du ihn hast.

Die Angst, die Quellen könnten verschwinden aus dem schnelllebigen www (ganz besonders Foren). Die Erfahrung spricht leider dafür. Als Beispiel sei
>
genannt; die Site verlottert seit Jahren und vieles aufwändig ausgearbeitetes Content ist unwiderruflich im Nirwana verschwunden.

Das gibt dir aber trotzdem nicht das Recht, ungefragt urheberrechtlich geschütztes Material zu verbreiten.

Summa summarum - Du hast mich überzeugt. Ich werde künftig eine Protokollierung meiner Anfragen anfertigen. Ich weiß noch nicht wie ich auf unbeantwortete Antworten reagiere, aber das werde ich auch noch herausbekommen. Zwar steigt nun der Aufwand enorm an (20% an Zeit die ich auch an Qualitätsverbesserung verwenden hätte können), aber es ist unvermeidlich, wie du aufgezeigt hast. Zumindest Guter Willen oder Symbiose-Gedanken hin oder her, das zählt eben nicht. Man kann froh sein, dass Verlinkungen nicht angefragt werden müssen.

Noch einmal: wird auf eine Anfrage von dir nicht geantwortet, darfst du es nicht verwenden. Ausserdem kann ich mir nicht vorstellen, dass es dir jemand erlaubt, eine Kopie auf deinem Rechner abzulegen.

@Guter Wille etc.: Ganz ehrlich: Willst du, dass von dir verfasste Inhalte irgendwo auftauchen und du weißt es noch nicht mal? Kann ich mir nicht vorstellen.

Letzenendlich würde ich dich bitten, eine Backupkopie deines Inhalts auf meinen Server bzw. Computer anzufertigen zu dürfen, um in Falle eines Falles nicht auf den externen Link angewiesen zu sein (welcher i.d.R. als einzige Quelle fungiert).

Der Artikel steht auf einer Plattform mit über 200.000 Benutzern (tutorials.de) und ich sehe keinen Sinn dahinter ein "Backup" für eine Seite mit 10 Visits pro Tag anzufertigen. Sorry. Du kannst gerne verlinken, das steht dir frei.

06.07.2008 - 17:43 Uhr

Mein GDI+ Artikel wurde ursprünglich als PDF auf meiner Website angeboten und später auf tutorials.de publiziert. Auf meiner Website ist es nicht mehr vorhanden, das ist korrekt so.

Aber:
a) Dieser Artikel wurde von mir unter oben genannten Link der Öffentlichkeit zur Verfügung gestellt. Dies bedeutet, dass ihn jeder lesen und die Beispiele darin ausprobieren kann. Es heißt jedoch nicht, dass dieser Content verwendet wird, um ein 10-Sekunden PDF daraus zu erstellen und auf der eigenen Webseite zu hosten.

b) Ja, du hast natürlich meinen Namen angemerkt. Gut. Aber hast du mich auch gefragt, ob ich diesen Artikel überhaupt auf deiner Site sehen möchte? Nein, hast du nicht. Und genau da liegt das Problem.

Du selbst schreibst in deinem Impressum:

Alle unter wubb.de veröffentlichten Texte und Bilder unterliegen dem Urheberrecht von (Name entfernt) und dürfen nur mit ausdrücklicher Erlaubnis mit Quellenangabe kopiert, weitergeleitet oder vervielfältig werden. Bei elektronischer oder schriftlicher Veröffentlichung ersuche ich um eine kurze Benachrichtigung per E-Mail und um ein Belegexemplar.

Du willst also, dass man dich um ausdrückliche Erlaubnis fragt, ebenso, dass die Quelle angegeben wird (eine Quellenangabe im Internet enthält auch immer die Angabe der URL unter welcher der Inhalt gefunden wurde) und du bittest um eine kurze Benachrichtigung als auch ein Belegexemplar.

Wieso tust du nicht das, was du von anderen erwartest? Und wieso willst du das Belegexemplar? Ganz klar. Du willst ja schließlich nicht, dass es absolut billig aussieht und somit eventuell dein Name an Reputation verliert. Genau das sehe ich auch so.

Ich bin in der Community tätig, weil ich gerne Menschen helfe. Daher stelle ich auch Inhalte zur Verfügung. Ich bekomme jedoch einen Hals², wenn einfachste Grundlagen nicht eingehalten werden. Und das ist hier auch der Punkt.

Du konntest den von mir angebotenen Inhalt im Internet nicht mehr finden? Und das obwohl du gesucht hast? Nein. Bei Google stehts an erster Stelle wenn nach dem Titel gesucht wird. Auch auf CodeZone ist eine Verlinkung zu finden (auf Google übrigens an 3. Stelle).

Bis auf eine Ausnahme habe ich die Quellen namentlich immer erwähnt. Bei einigen steht noch eine Anfrage aus.

Wie schon erwähnt: Namentliche Quelle reicht nicht. Eine Quellenangabe umfasst auch den Link zu einer vertrauenswürdigen Fundstelle bzw. zum Content-Ersteller. Anfragen müssen VOR der Veröffentlichung eingeholt werden.

Ich setze mich für ein weltoffenes Internet mit Hyperlinks ein. Das heißt natürlich nicht, dass man damit sämtliche Coprights missachtet.

Ich hätte mich dazu gar nicht geäußert, wenn du einfach auf den verfügbaren Content verlinkt hättest - wie du es ja auch propagierst. Kein Hyperlink und Copyright missachtet.

Ich wehre mich aber gegen die Behauptung, deren Inhalte als zueignen gemacht zu haben.

Ich habe gesagt, dass du meine Inhalte in ein Low-Budget-PDF kopiert hast. Und das ist nicht rechtens.

Ich persönlich würde mich freuen, wenn mein frei angebotenes Material, wo ich keine Verteilungsbeschränkungen vermerkt habe natürlich (unverändert) weitergegeben wird.

Blauäugigkeit. Bei Images, die via Bildersuche im Internet auftauchen, ist auch keine Beschränkung vermerkt und dennoch dürfen sie nicht ohne Rücksprache verwendet werden.

Url-Grabber verändern auch nichts und stellen den Content as-it-is unter irgendeiner URL ins Internet. Ist ja auch nicht legitim, hm?

Wenn meine Site kommerziell und voller Werbung wäre, hätte ich das alles mit Sicherheit nicht reingestellt. Sie ist und bleibt aber privat und werbefrei (mit gemeinnützigem Hintergedanke). Ob das was an der Sachlage ändert?

Nein. Tut es nicht.

06.07.2008 - 14:57 Uhr

Deine Seite mag für den einen oder anderen Durchaus sinnvoll sein (obliegt jedem selbst zu entscheiden), aber bei dieser Aussage wird es mir schon mal eben schlecht:

Alle hier angebotene Ressourcen sind frei und legal im www erhältlich!

Nur weil etwas frei im Internet verfügbar ist, heißt es noch lange nicht, dass es ohne Erlaubnis für eigene Zwecke verwendet werden darf.

Noch dazu, wenn die Quelle nicht verlinkt wurde, das resultierende PDF ein zusammenkopierter Artikel von mir ist, noch dazu absolut schlecht formatiert usw.

Aus deiner Sicht wäre es also sehr zielführend, dich mit mir in Kontakt zu setzen.

07.05.2008 - 10:02 Uhr

Das was du willst ist wohl das, was wir von ASP.NET als MasterPages kennen. Dieses Konzept wird eigenständig in WPF nicht unterstützt, aber es gibt dazu einen netten Artikel, der dir weiterhelfen sollte:

WPF "Master Page" like functionality

29.04.2008 - 16:55 Uhr

Ok, also kann ich mir das folgendermassen vorstellen. Mein ListViewItem hat ein Child, welches mein Item aus dem Source entspricht. In meinem ControlTemplate bin ich auf der Ebene des Childs und kann deshalb mit Binding auf die Eigenschaften von meinem Typ zugreifen. Um nun wieder zu meinem Parent (dem ListViewItem) zu gelangen, muss ich TemplateBinding nutzen?

Nein, wenn du die ItemsSource-Eigenschaft zugewiesen hast, dann gibt es das ListViewItem so gesehen nicht mehr. Das würde es nur geben, wenn du folgendes hast:


<ListView>
  <ListViewItem>FirstItem</ListViewItem>
  <ListViewItem>SecondItem</ListViewItem>
</ListView>

In diesem Fall sähe der Logical Tree so aus:


ListView
 |- ListViewItem
     |- String
 |- ListViewItem
     |- String

Einfach mal mit dem LogicalTreeHelper bzw. dem VisualTreeHelper spielen 🙂

Schade, dass soetwas nur so umständlich ist. Eine Möglichkeit wie Key="Mein Statischer Wert {Binding ...}" wäre viel praktischer 🙂

Vielleicht geht es auch viel einfacher 🙂

29.04.2008 - 13:19 Uhr

In deiner Variante würde das Admin-Menü ja immer erscheinen ...

Ausserdem sind ValidationRules nicht unbedingt dafür gemacht. Das würde ich anders lösen.

Wenn es sich nicht weiterhin stört, dass das Admin-Menü immer sichtbar ist, kannst du den XPath bei deinem Binding auf

XPath="/tools/tool[@type='admin']"

stellen. Dann erscheinen auch nur alle Einträge für Admin. Ob das Menü dann sichtbar ist oder nicht, solltest du anders lösen.

29.04.2008 - 13:15 Uhr

Das heisst also, ich kann sowohl "{Binding Path=EigenschaftMeinesTyp}" und "{Binding Path=EigenschaftListView}" nutzen?

Für den zweiten Fall gibt es das TemplateBinding. Mit Binding alleine kannst du entweder Eigenschaften des übergebenen Typs binden oder unter Angabe von ElementName Eigenschaften eines anderen Elemente.s

Du hast geschrieben "Dieser Typ IST ein ListViewItem". Das ControlTemplate bezieht sich doch genau auf ein Item und das kann doch nur von einem Typ sein. Ich verstehe die Logik irgendwie nicht. Befinde ich mich in einem ListViewItem oder in einem Item von meinem Typ? Ich stelle mir das so vor, dass ich mich in dem Design Bereich einer foreach Schleife befinde. Ich hoffe du verstehst was ich meine.

Ok, ich versuchs nochmal.
Ein ListView besitzt Items. Diese Items sind ursprünglich vom Typ ListViewItem. Dahingehend kann man dann beispielsweise ein ControlTemplate erstellen. Dieses wird auch auf die ListViewItems entsprechend angewandt. Wenn du nun die ItemsSource setzt, dann befindet sich in der Items-Auflistung eine Collection deiner Objekte.

Ok danke, aber in dem Fall kann ich nun nur an den Pfad binden. Ich möchte aber sozusagen den Sourcestring aus 2 Bindungen zusammensetzen. D.h. sowas wie Pfad (Bindung1) + Dateiname (Bindung2).

Erstelle dir eine Methode/Eigenschaft, welche dir den Gesamtpfad zurückgibt und diesen bindest du dann einfach.

Eine Kleinigkeit ist mir auch noch unklar. Wenn ich mich in dem ControlTemplate befinde, habe ich nur einen Bezug auf ein ListViewItem. Dieses ControlTemplate nutze ich in einem UserControl. Was ist aber wenn ich aus dem ControlTemplate auf Eigenschaften des UserControls zugreifen möchte. Ich habe da folgendes Problem. Mein UserControl hat eine Eigenschaft DefaultImageSource. Wenn kein ImagePath in meinen Items vorhanden ist, soll dieser DefaultImageSource genutzt werden. Meine Idee in der Sache wäre ein Trigger, der ja (wahrscheinlich) auf die Eigenschaften des Items zugreifen kann. Aber wie sag ich dem Trigger dann, dass er den ImageSource Pfad in dem Fall auf DefaultImageSource setzen soll?

Dein UserControl ist ja auch nur ein Element. Probiere es mit einem Binding unter Angabe des ElementName und verweise auf deine entsprechende Property. Achte darauf, dass es sich um eine DependencyProperty handelt. Das sollte funktionieren, ohne es jetzt getestet zu haben.

26.04.2008 - 18:41 Uhr

Gar nicht. Denn die Zelle als solches gibt es ja nicht. Du definierst mit deinem Grid ja nur einen Raster. Nun musst du aber auch definieren, was wo genau dargestellt wird. D.h. du definierst, dass beispielsweise in Spalte 0 und Zeile 1 ein TextBlock anzuzeigen ist. An diesen kannst du auch etwas binden.

Das sollte bei deinen Überlegungen weiterhelfen.

26.04.2008 - 16:46 Uhr

So, wie versprochen, hier ein kleines Beispiel. Es handelt sich dabei um ein Window und dieses besitzt mehr oder weniger nur eine ListView. Diese ListView bekommt über die ItemsSource eine Collection mit Elementen vom Typ Person, welcher wie folgt aussieht:


public class Person
{
    public String Firstname { get; set; }
    public String Lastname { get; set; }
    public String PicturePath { get; set; }
}

Nun wurde von mir das ControlTemplate ausgetauscht. Was macht dieses?

  1. Es stellt das jeweilige Element in einem Grid dar (ListViewItem). Die linke Spalte ist befüllt mit einem Image, in der rechten Zeile befinden sich zwei Zeilen. In der ersten wird der Nachname fett angezeigt, darunter der Vorname.

  2. Es ist darauf zu achten, dass den einzelnen Elementen im ControlTemplate ein Name zugewiesen wird. Dadurch kann über die Trigger darauf zugegriffen werden.

Hier nun das gesamte XAML-Markup:


<Window x:Class="DotNetGui.WpfListViewDemo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title=".NET GUI - ListView - Resize Image Demo" Height="300" Width="300">

    <Window.Resources>

        <Style x:Key="{x:Type ListViewItem}" TargetType="{x:Type ListViewItem}">
            <Setter Property="SnapsToDevicePixels" Value="true"/>
            <Setter Property="OverridesDefaultStyle" Value="true"/>
            <Setter Property="Template">
                <Setter.Value>

                    <ControlTemplate x:Key="{x:Type ListViewItem}" TargetType="{x:Type ListViewItem}">
                        <Border Padding="2" SnapsToDevicePixels="true" Background="{TemplateBinding Background}">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="50"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="25"/>
                                    <RowDefinition Height="25"/>
                                </Grid.RowDefinitions>

                                <Image Name="PersonPicture" Source="{Binding Path=PicturePath}" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Width="30"/>
                                <TextBlock Padding="2" Text="{Binding Path=Lastname}" FontWeight="Bold" Grid.Column="1" Grid.Row="0"/>
                                <TextBlock Padding="2" Text="{Binding Path=Firstname}" Grid.Column="1" Grid.Row="1"/>
                            </Grid>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter Property="Background" Value="LightBlue"/>
                                <Setter TargetName="PersonPicture" Property="Width" Value="50"/>
                            </Trigger>
                            <Trigger Property="IsSelected" Value="False">
                                <Setter Property="Background" Value="White"/>
                                <Setter TargetName="PersonPicture" Property="Width" Value="30"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <DockPanel>
        <ScrollViewer CanContentScroll="True" VerticalScrollBarVisibility="Auto">
            <ListView x:Name="PersonListView"/>
        </ScrollViewer>
    </DockPanel>
</Window>

Beachte bitte die Zeilen:

<Setter TargetName="PersonPicture" Property="Width" Value="50"/>

bzw.

<Setter TargetName="PersonPicture" Property="Width" Value="30"/>

Darüber kann direkt das Image-Element des ControlTemplates beeinflusst werden. Auf diese Weise kannst du sehr einfach (ohne sonstige Handgriffe zu tun), die Breite deines Images anpassen.

Ich hoffe das hilft dir soweit mal weiter bzw. zeigt dir auf, wie man Derartiges angehen kann. Hier noch der Screenshot meiner Beispielanwendung:

25.04.2008 - 09:52 Uhr

Die Items gehen über den Source in das ListView als BindingList<>

Kein Problem, ist ja auch nur eine Collection deiner Objekte.

1 u. 2) So ganz ist es mir nicht. Ich greife doch zB im Trigger auf Eigenschaften von ListViewItem (IsSelected) zu und binde auf der anderen Seite an Member von meinem Typ (ElementContent).

Neuer Tag, neuer Versuch 😉

Und zwar: Durch das ControlTemplate legst du ja fest, für welchen Typ es zuständig ist bzw. in welchem Typ es verwendet wird. Dieser Typ IST ein ListViewItem. Dieses bietet Eigenschaften an, die verwendet werden können (IsSelected zum Beispiel).

Nun fügst du eigene Objekte der Items-Auflistung hinzu (DataSource, wie auch immer). Diese werden für das DataBinding verwendet, d.h. er findet so auch den angegebenen Pfad, weil pro ListViewItem auf das Objekt geachtet wird, das darin enthalten ist.

  1. Ich habe z.B. eine statische Eigenschaft in einem Singleton Objekt. In meinem Fall habe ich z. B. einen Pfad. Nun möchte ich gerne den ImageSource setzen, Pfad (nicht im Item vorhanden) + Dateiname. Wobei der Dateiname in dem Item vorhanden ist.

Du kannst das über einen ObjectDataProvider in deinen Ressourcen machen und da das Ergebnis einer Methode etc. binden.

  1. D.h. um z.B. im ControlTemplate die Breite eines Image(Containers) per Trigger zu ändern, müsste ich diese Eigenschaft an eine (Dummy) Eigenschaft des Items binden?
    Nun sind wir aber bei Problem 1 u. 2. Im Trigger kann ich doch nur auf die Eigenschaften von ListViewItem und nicht meinem Typ zugreifen.

Ich versuche die Zeit zu finden, dir da ein Beispiel zu erstellen.

24.04.2008 - 14:30 Uhr
  1. Damit **IsSelected **von dem Trigger gefunden werden kann, muss der **TargetType ****ListViewItem **sein. Die Items sind aber von dem Typen myType. Nun könnte ich von **ListViewItem **ableiten. Dabei bekomme ich aber Probleme mit dem OR-Mapper. Dieser stört sich daran, das manche Member nicht als virtual gekennzeichnet sind. Theoretisch könnte ich mir die Arbeit machen, und die Member neu erstellen und auf die Basisfunktionalität mappen. Sprich "... new virtual ..."

Wie genau hängst du dein ListViewItem rein? Sagst du:


ListViewItem lvi = new ListViewItem();
lvi.Content = new MyType(myImgPath);

Eine ListView besteht nun aus Items. Jedes Item ist und bleibt ein ListViewItem. Was du aber über ein ControlTemplate machen kannst ist, dass du die Gestaltung eines ListViewItems austauschen kannst. Nicht aber, dass es sich nachwievor um ein ListViewItem handelt. Daher muss der TargetType auch ListViewItem sein, damit du Informationen beziehen kannst, die Rückschlüsse darauf zulassen, dass das Item selektiert wurde etc.

Dein Verständnisproblem an der Sache ist folgendes:
Du musst angeben, worauf sich das ControlTemplate bezieht. In deinem Fall ListViewItem. Ebenso möchtest du auf Ergeignisse des ControlTemplates reagieren. Dieses wird repräsentiert durch ein ListViewItem. Dieses definiert nun auch die Ereignisse, die du via Trigger abfangen kannst.

Das Binding jedoch, bezieht sich auf das was das ListViewItem enthält und nicht auf die ListViewItem selbst (das wäre das TemplateBinding).

So gesehen solltest du mit deinem O/R Mapper auch keine Probleme bekommen.

  1. Wie kann es sein, dass alles ordentlich dargestellt wird? Das **ImgPath **und **ElementContent **gefunden werden, kann ich mir damit erklären, dass **ListViewItem **als **TargetType **ignoriert wird und **myType **diese Eigenschaften enthält. Wie ist dies aber mit **IsSelected **und Selector.IsSelectionActive, diese Eigenschaften sind nicht in myType vorhanden und können trotzdem fehlerfrei genutzt werden (Die GUI funktioniert, wie sie soll).

Siehe oben.

  1. **TextBlock.Text **ist an **ElementContent **gebunden. Wie kann ich einen Prefix (statischer Text und eine Eigenschaft eines Singleton-Objekts) hinzufügen?

Kannst du da bitte genauer beschreiben, was du vor hast?

  1. Wie kann ich das **ControlTemplate **manipulieren. D.h. wie kann ich z.B. durch einen Trigger bei **IsSelected **die Breite des Bildes ändern.

Hier könntest du beispielsweise mit DataBinding arbeiten. Breite des Images wird beispielsweise an eine Eigenschaft deines Objektes gebunden, welches wiederum über den Trigger neu gesetzt werden kann (nicht getestet, müsste aber funktionieren).

24.04.2008 - 14:16 Uhr

Eine App.xaml habe ich ja leider nicht (DLL) und bringt bei den Controls auch nichts.
Bei den Styles werden selbst die "primitiven" Controls wie z.B. Button oder Labels angesprochen.

Wenn man hört wie toll, WPF ist, wird oft gesagt:

"Man kann Styles definieren und dafür sorgen, dass alles gleich aussieht"

So einfach ist es aber nicht, dies ist nur die halbe Wahrheit. Wieso gibt es dafür keine "globale" Lösung für eine komplette DLL.

Geht doch. Schon wenn du eine Custom Control Library anlegst, wird auch ein Themes-Ordner mit angelegt. Darüber kannst du das Aussehen für alle Elemente aus deiner DLL ja steuern. Wenn du dies nun flexibel gestaltest, kannst du es so machen, dass bei einer Definition auf Anwendungs-Ebene deine Controls angepasst werden.

Was ich NICHT wollen würde ist, dass ich eine Control Library einbindet und DIESE definiert wie meine Buttons auszusehen haben. Kontraproduktiv. Ich möchte eine Controls Library einbinden, die mit einem Default-Aussehen kommt und ich ICH entsprechend anpassen kann.

Das ist auch Sinn und Zweck einer derartigen Library.

Wäre es nicht schön, für ein Namespace ressourcen hinterlegen zu können 🙂
Wenn dazu noch die Funktionaliät von partiellen XAML Files existieren würde, wären meine Probleme gelöst.

Damit wären keine Pobleme gelöst:

  1. In einer Assembly können sich mehrere und unterschiedliche Namespaces befinden
  2. Ein Namespace kann sich über mehrere Assemblies hinwegziehen

Dadurch wäre es äußerst sinnlos, Ressourcen auf Namespace-Ebene zu vergeben, zumal ein Namespace nur eine logische Kategorisierung ist und nichts weiter.

Und genau zu diesem Zeitpunkt, wäre die Aussage "Man kann Styles definieren und dafür sorgen, dass alles gleich aussieht" für mich auch wahr.

Kann man dann. Aber du sattelst hier das Pferd von der falschen Seite auf.

Wieso kann man Styles nicht genauso wie Klassen betrachten. Somit könnte man die Styles ohne Probleme einbinden und auch viel kompfortabler davon ableiten.

Styles können ja vererbt werden.

Für mich ist die Sache ein unnötiger riesen Verwaltungsaufwand und ist auch für eine Erweiterbarkeit nicht sonderlich hilfreich.

Sehe ich nicht so. Mit Hilfe der Styles ist es erst überhaupt möglich, Controls anders zu gestalten. Und das unabhängig von dem implementierten Code. Dass jedoch nicht alles über Styles abgedeckt werden kann sollte auch klar sein. Imho ist es eine Gestaltungshilfe und weniger ein Implementierungsfeature.

24.04.2008 - 14:06 Uhr

Könntest du mal deinen aktuellen Stand posten bzw. gleich dein Projekt anhängen?

24.04.2008 - 13:42 Uhr

Ah, hab überlesen, dass du bereits geschrieben hast, wie genau du es machst.

Also, in meinen Anwendungen wurde das so gelöst:

  1. Genau so wie ich es gepostet habe bzw. wie du es anscheinend auch machst
  2. Die Ressourcen werden in meinen Anwendungen global eingebunden, d.h. in der App.xaml.

Damit habe ich grundsätzlich überhaupt keine Probleme. Wenn ein Control einen speziellen Style besitzen soll, dann wird dieser explizit zugewiesen.

24.04.2008 - 13:39 Uhr

Cider hat durchaus noch seine Macken.

Kannst du das Control herausgeben, oder ist es für ein Unternehmen? Wenn du es rausgeben kannst/darfst, dann würde ich es mir ansehen.

24.04.2008 - 13:38 Uhr

Ok, du hast es auf das Thema Dokumentation bezogen.

Nun gut, auch hier gibt es entsprechende Ressourcen. Sicherlich wird noch nicht alles was möglich ist abgedeckt, aber was ist auch ein schier unmögliches Unterfangen. Die grundsätzliche Dokumentation der MSDN ist nicht schlecht, auch werden alle Konzepte erklärt, inklusive sämtlichen Klassen, wo ebenfalls Beispiele vorkommen.

Dann gibt es natürlich viele Blogs mit zahlreichen Beiträgen wie bestimmte Probleme gelöst werden können, als auch diverse Communities, die sich mit diesem Thema beschäftigen.

24.04.2008 - 13:27 Uhr

Entferne mal das ..\ aus deiner Pfadangabe.

24.04.2008 - 13:23 Uhr

Was kann dadurch beispielsweise nicht entwickelt werden?

Die Konzepte wurden geändert und angepasst, damit eben viele Dinge wesentlich besser und effizienter entwickelt werden können. Ohne diese Änderungen hätte etwas wie die WPF das Licht der Welt erst gar nie erblickt.

Ausserdem ist es fatal zu sagen, dass etwas nicht gemacht werden kann, nur weil sich eben etwas daran geändert hat, wie ich es bisher machte.

Alleine das Eventsystem: Direct Events wie sie beispielsweise in den Windows Forms gehandhabt werden decken einfach nicht sämtliche Möglichkeiten ab. Daher wurden Bubbling und Tunneling Events eingeführt. Nichts desto trotz können Direct Events immer noch verwendet werden. Dies entspricht nun keiner kompletten Änderung, sondern eine Erweiterung des bisherigen Konzeptes und somit auch eine Erweiterung der bisherigen Möglichkeiten. Das ist doch gut so.

24.04.2008 - 13:21 Uhr

Also einen CLR-Namespace musst du in diesem Fall immer angeben. Da sich das Control jedoch in der gleichen Assembly befindet, kannst du den "assembly="-Part weglassen.

Zu deiner Exception: Hast du auch eine InnerException?

24.04.2008 - 13:17 Uhr

Ist nicht wirklich schwierig zu erledigen.

Erstelle dir ein Resource Dictionary, welches deine Basisstyles/-templates enthält. Die anderen Resource Dictionaries (mit Spezialisierungen) verweisen nun auf dieses Basis Dictionary, d.h. binden dieses in sich selbst ein. Das kann so erledigt werden:

Im spezialisierten Resource Dictionary einfach folgendes Markup verwenden (Shared.xaml ist das Basis Dictionary):


<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>

24.04.2008 - 13:14 Uhr

Vergesst nicht, WPF ist noch nicht so alt. Es ist klar, dass es jede Menge Dokumentation zu Themen gibt, die bereits 10 Jahre oder mehr hinter sich haben.

Mit der WPF wurde 2003 begonnen und 2007 veröffentlicht. Da kann natürlich noch nicht soviel Material zu bestehen. Zusätzlich haben sich natürlich grundlegende Konzepte geändert (immerhin wird hier einiges zusammen geführt, WEB, GDI+, Windows Forms, DirectX, etc.). Das ergibt natürlich einen gewaltigen Unterschied zur (beispielsweise) Windows Forms Entwicklung. Einige Dinge funktionieren einfach anders, als man es bisher gewohnt war.

Dies sehe ich nicht unbedingt als Problem an. Es ist lediglich eine Gewohnheitssache, die sich einschleicht, wenn man einige Zeit damit gearbeitet hat.

23.04.2008 - 18:32 Uhr

Du hast das ja alles in eine Page gegeben. Verwende eine Resource Dictionary. D.h. nicht "New Page", sondern "New Item" und dann "Resource Dictionary".

Solltest VS in deutscher Sprache haben, na dann viel Spaß. Gerade gesehen, dass das da ja fürchterlich klingt. Anbei ein Screenshot dessen, was du verwenden solltest.

23.04.2008 - 18:30 Uhr

Glaub das geht net. Da musst schon ins XAML greifen ...

23.04.2008 - 18:29 Uhr

WPF-Anwendungen starten mit 2 Threads:

  • 1 für Rendering
  • 1 für UI

Für UI ist der Dispatcher zuständig.

Weitere Informationen unter http://msdn2.microsoft.com/en-us/library/ms741870.aspx

21.04.2008 - 10:08 Uhr

Ja, habe es als Link hinzugefügt.

Mein Control war jedoch sehr simple aufgebaut: 2 TextBoxen + einen Button, der lediglich eine MessageBox ausgibt. Sonstige Abhängigkeiten sind nicht gegeben.

Was habe ich gemacht:

  1. Element per Link eingebunden
  2. Namespace angegeben
  3. Element via Präfix eingebunden und zur Anzeige gebracht

Funktioniert.

Wie sieht es bei dir mit Abhängigkeiten aus? Werden Dinge nachgeladen, die du eventuell nicht referenziert hast (da müsste normalerweise aber schon früher eine Meldung kommen).

Hast du mal ein Clean auf das Projekt gemacht und dann nochmals probiert?

Hat deine Exception eventuell eine InnerException die aussagekräftiger ist?

21.04.2008 - 10:02 Uhr

Du musst natürlich in deiner Anwendung darauf verweisen. Wenn es global für die Anwendung gelten soll, dann muss es in der App.xaml definiert sein (bzw. manuelles Laden würde auch funktionieren).

Grundsätzlich legst du einfach Ressource Dictionaries an und verweist einfach auf sie. Dann kannst du dir noch aussuchen, ob du sie reinkompilieren willst oder nicht. Diese Dictionaries kannst du dann in einem anderen Projekt genauso einbinden. Ist übrigens recht sinnvoll, wenn alle deine Anwendungen den gleichen Style verwenden sollen.

21.04.2008 - 09:59 Uhr

Bekommst du einen Hinweis darauf, was genau null ist?

Ich hab das soeben ausprobiert und es funktioniert tadellos. Verweist du eventuell innerhalb deines Elementes auf andere Elemente?

21.04.2008 - 09:30 Uhr

Eine TreeView gibt es auch unter WPF (Übersicht der Steuerelemente unter Windows Forms und WPF).

Den FlowDocumentReader brauchst du da ja eigentlich nicht.

Soll die XML-Datei editiert werden können, oder geht es dir nur darum, die Datei einzulesen und scrollbar darzustellen? Wenn ja, dann reicht ein TextBlock auch. Da kannst du dann einen ScrollViewer arbeiten.

21.04.2008 - 09:25 Uhr

Wie genau bindest du es ein? Zeig kurz wie du auf dein Element zugreifst.

Normalerweise legst du eigene Elemente in einer Library ab, referenzierst diese DLL, vergibst einen CLR-Namespace und greifst dann über das Präfix auf das Element zu.

17.04.2008 - 10:57 Uhr

Vielleicht hilft das weiter:
Grafiken mit runden Ecken

17.04.2008 - 10:35 Uhr

Hy
Ist eigentlich auch nicht SL 2.0, sollte aber von der Technik her gehen, da SL 2.0 ja eine xbap-Datei kompiliert und das ist nichts anderes als WPF, somit sollten eigentlich auch die meisten Controls von WPF zur Verfügung stehen (wenn auch nur in XAML).

Das würde auch implizieren, dass am Zielrechner das komplette .NET Framework installiert sein muss. Und genau das sollte ja bei Silverlight vermieden werden.

16.04.2008 - 13:58 Uhr

Eigentlich sollten Informationen einer Form nicht von ausserhalb geändert werden. Wenn dies notwendig ist, kann dies über eine Objekt-Instanz gemacht werden, das wäre auch der saubere Weg (sprich Data Binding und Co.)

Grundsätzlich würden sich sonst aber Properties anbieten.

Es hängt schließlich auch davon ab, was er im Endeffekt tun möchte.

16.04.2008 - 13:45 Uhr

Das würde ich so auch nicht machen. Wenn du Informationen an ein Formular weitergeben möchtest, dann tu das über den Konstruktor



public Form1(String username) 
{
    InitializeComponent();
    
    this.UsernameTextBox.Text = username;
}

Ist doch viel sauberer so. Solltest du mehr als 2-3 Daten zu übergeben haben, dann erstelle eine eigene Klasse und übergib eine Instanz davon an dein Formular.

14.04.2008 - 14:02 Uhr

Da ich deine genaue Aufgabenstellung nicht kenne, kann ich dir natürlich nicht sagen, ob es der für dich optimale Weg ist. Du könntest innerhalb deiner Tabs ein Frame verwenden und dort Pages laden. Damit könntest du das auftrennen. Eine Frage stellt sich dann natürlich, ob du nicht eventuell gleich eigene Controls entwickelst, die übersichtlich eingebunden werden können. Dadurch hast du natürlich auch eine Trennung der einzelnen Elemente.

14.04.2008 - 14:00 Uhr

Der Hintergrund liegt darin, dass es sich dabei um eine Browseranwendung handelt und diese wird aus Sicherheitsgründen in einer Sandbox ausgeführt.

Weitere Informationen dazu gibt es unter http://msdn2.microsoft.com/en-us/library/aa970906.aspx.

14.04.2008 - 13:48 Uhr

Ich sehe die Möglichkeit hier eher als gering an. Wenn es sich um eine Page handelt zu der navigiert werden soll, dann kannst du diese vermutlich selbst ansehen, da sie in deinem Projekt vorhanden ist.

Zur Auswertung der Source-Eigenschaft müsste zu dem im Hintergrund die Navigate()-Methode aufgerufen werden, damit das Frame tatsächlich zur Page navigiert, was im Designer selbst wenig Sinn hätte und meist auch nicht wirklich benötigt werden würde.

14.04.2008 - 13:19 Uhr

Könntest du das gesamte XAML und den von dir verwendeten Source posten. Wenn es nicht vollständig ist, kann es nur sehr schwer nachvollzogen werden.

07.01.2008 - 10:12 Uhr

Ab sofort steht die fünfte Ausgabe des .NET BlogBooks zur Verfügung.

In dieser Ausgabe gibt es jede Menge neuer Beiträge aus den Themenbereichen Windows Presentation Foundation, C# 3.0, Tools und vielen mehr.

Aktuell werden auf knapp 320 Seiten Erfahrungen, Erklärungen und Beispiele für den .NET Entwickler bereit gestellt.

Weitere Informationen sind auf der Projektseite des .NET BlogBooks zu finden.

PS: Auch ein Gewinnspiel gibt es dieses Mal: ein Ticket für die VSone.

02.01.2008 - 16:47 Uhr

Probier es mit der SharpZipLib.

31.12.2007 - 13:05 Uhr

Zu 98% 2008, in ganz seltenen Fällen noch 2005.

28.12.2007 - 14:26 Uhr

Gerne. Am besten gleich hier im diesem Thread (Wenn Dir das nicht zu unübersichtlich ist). Wie sieht die Architektur des Applikationsservers aus, den Du als Diplomarbeit entwickelt hast?

Eher nicht öffentlich im Thread.

Zum .NET Remoting:
Ich hab mir den Source jetzt nicht angesehen, aber so am Rande mitbekommen, dass die Datenübertragung per .NET Remoting passiert? Hier würde ich beispielsweise eher WCF einsetzen, zumal diese "Technologie" von Microsoft weiterhin unterstützt wird, verbesserte Funktionalität bietet und .NET Remoting schon jetzt stiefmütterlich behandelt wird.

Zudem würde ich den Persistance-Layer wesentlich erweitern. Oder zumindest die Möglichkeit bieten, entsprechende O/R Mapper zu verwenden (siehe JBoss).

28.12.2007 - 13:59 Uhr

Geht es dir um die Skin-Funktionalität? Wenn ja, dann kannst du dir das Laden von XAML zur Laufzeit ersparen.

Erstelle ein ResourceDictionary, welches die Darstellungen definiert.

Hier findest du ein Beispiel und Erklärungen:
http://blogs.vertigo.com/personal/alanl/Blog/Lists/Posts/Post.aspx?List=d8ffd567-df86-4de5-9b5a-00fd37f58cda&ID=15

28.12.2007 - 13:51 Uhr

Kannst du ja beispielsweise beim User nachfragen:


SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "RichText|*.rtf";
sfd.DefaultExt = ".rtf";
sfd.Title = "Save RichText";
sfd.FileOk += new System.ComponentModel.CancelEventHandler(sfd_FileOk);
sfd.ShowDialog();

....


private void sfd_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
{
    SaveFileDialog sfd = (SaveFileDialog)sender;
    if (!String.IsNullOrEmpty(sfd.FileName))
      // Save here ...
}

28.12.2007 - 12:05 Uhr

Session-State-Handling ist kein Feature, welches ein Applikationsserver zwingend benötigt. Bei COM+ (Enterprise Services) - und das ist ja auf jeden Fall ein vollwertiger Applikationsserver - gibt es auch kein Session-State-Handling (Bitte um verbesserung, falls es das dort doch in irgendeiner Form geben sollte). Sitzungsstatus wird eigentlich nur von Web-Anwendungen benötigt und ist damit Sache des Webservers. Der Webserver ist bei einer Web-Anwendung für das Front-End zuständig, der Applikationsserver für die Geschäftslogik. Die Geschäftslogik sollte, wegen der Skalierbarkeit, möglichst statuslos implementiert sein. Der Status wird vom Client gehalten. Bei einem Web-Client muss der Webserver eben den Status halten (HTTP ist ja statuslos). Bei einem Windows-Client wird der Status vom jedem Client-Computer selber verwaltet. Deshalb brauchen Web-Clients eine Sitzungsstatus-Verwaltung und Windows-Clients nicht.

Was COM+ / .NET Enterprise Services anbieten sind grundsätzlich nicht vordergründig, da durchaus schon ein paar Jahre auf dem Rücken. Ich sehe Sessionhandling es definitiv als Feature. Sessionhandling jedoch nicht im herkömmlichen Sinne für Web-Appications gedacht. Schließlich muss auf dem Application Server nicht unbedingt ein Webserver aufsetzen (wobei der Webserver selbst auch für mehr als nur das Front-End zuständig ist).
Es besteht die Möglichkeit, dass es mehrere Applicationserver gibt, um Lasten zu teilen. Jede Anwendung die im Context des Applicationserver läuft, kann nun Statusinformationen halten, die garantieren, dass Requests in der korrekten Reihenfolge ablaufen, dass sonstige Manipulationen nicht stattfinden können. Diese müssen von Applicationserver zu Applicationserver weitergereicht werden, sollte einer ausfallen, wobei wir auch schon beim Thema Ausfallssicherheit und Verteilbarkeit wären.

Einige Applikationsserver können zwar auch direkt als Webserver eingesetzt werden, deshalb ist Session-State-Handling aber kein erforderliches Feature, damit sich ein Prozess "Applikationsserver" nennen darf.

Natürlich ist es kein erforderliches Feature, aber durchaus ein sehr sinnvolles und nützliches Feature, wenn größere Anwendungen darauf laufen sollen.

Was den angesprochenen Punkt "Verteilbarkeit" angeht, hast Du natürlich recht. Mein kleiner Beispiel-Applikationsserver lässt sich momentan nicht ohne Umbauten auf verschiedene Rechner verteilen. Clusterfähig ist er auch nicht. Das Projekt wurde aber auch nicht mit dem Ziel entworfen, den großen Applikationsservern am Markt den Rang abzulaufen (Wobei es da im .NET-Umfeld gar nicht so viel gibt), sondern um einen praxisnahen Einstieg in die Entwicklung von verteilten mehrschichtigen Anwendungen zu geben. Selbst bei 200 Benutzern ist eine Verteiltung der Geschäftsdienste auf mehrere Maschinen in den meisten Fällen nicht nötig (ist pauschal aber nicht zu sagen, da es von der Anwendung abhängig ist). Für den Anfang kommt man selbst mit diesem kleinen Applikationsserverchen recht weit. Durch die Kapselung der Kommunikation durch die API, steht auch nichts im Wege, die Verteilbarkeit nachzurüsten (oder vielleicht auch von Remoting auf WCF zu wechseln). Besonders Session-State-Handling lässt sich mit ein paar Handgriffen einbauen (wenn man es wirklich braucht).

Da hast du natürlich vollkommen recht. Ich wollte ja auch nicht dein Projekt/Beispiel schlecht machen, sondern vielmehr habe ich mich an dem Wort vollständig gestoßen. Das ist auch schon der gesamte Hintergrund.

In der Tat gibt es im .NET Bereich kaum einen Applicationserver (die Enterprise Services zähle ich nicht, da diese lediglich COM+ kapseln). Aus diesem Grund habe ich dazu auch eine Diplomarbeit geschrieben und einen .NET Application Server gebaut 😉 (hier schließt sich ein Kreis).

Obwohl ich mein Projekt zunächst mal verteidige, freue ich mich sehr über solche kritischen Meinungen. Das Projekt ist eben erst geboren und muss erst noch reifen und gedeien. Mit Hilfe der Community wird es das hoffentlich auch recht schnell 😉.
Ich möchte auch noch einen Web-Client nachlegen. Da wird sich zeigen, ob eine Sitzungsverwaltung im Applikationsserver sinnvoll ist, oder ob ich das nicht besser auf den IIS abwälze.

Eventuell können wir uns hier ja einmal unterhalten und ein paar Modelle durchgehen, schließlich könnten eventuell beide Seiten daraus profitieren.

28.12.2007 - 09:42 Uhr

Da so eine genaue Grenze zu ziehen finde ich nicht so gut. Ich sehe das eher so:

a) Über Linq schreiben, dann gleich alles erwähnen
b) Gar nichts über Linq schreiben

Bei der jetzigen Form kommt halt schnell das Gefühl der Unvollständigkeit auf und das sollte nicht sein. Just my 2 cents.

27.12.2007 - 21:31 Uhr

Hi,

also beim Thema LINQ fehlt ja schon einiges, Linq to Objects, Linq to SQL, Linq to XML usw.

Weiters fehlen (oder ich hab es nicht gefunden)

  • Anonyme Typen
  • Automatic Properties
  • usw.

Also noch genug Arbeit 😉

Und eine Suche wäre auch noch sehr hilfreich. Aber sonst ganz gut gemacht, wenn auch nicht so 100%ig übersichtlich.

27.12.2007 - 21:09 Uhr

angeregt durch
>
, habe ich einen leichtgewichtigen aber vollwertigen Applikationsserver geschrieben.

Ich will dir nicht zu nahe treten, aber vollwertig kann man dein Beispiel nicht nennen. Es ist zwar ein nettes Beispiel für einen Application-Host. Zum Application-Server fehlt aber noch ein wenig. Session-State-Handling, Verteilbarkeit, usw.

Nichts desto trotz: Tolle Arbeit.