Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Portal
  • |
  • Mitglieder
Beiträge von IsNull
Thema: WPF und Terminalserver
Am im Forum: GUI: WPF und XAML

Hallo,

Wir haben bei einem Kunden von mir auf einem TS 2003 eine WPF Applikation am laufen. Im Normalfall gibt es wegen dem Rendering selber keine Probleme, schlimmstenfalls (hängt von der Hardware ab) schaltet WPF auf den Software Renderer, der sollte aber für normale Anwendungen ausreichend schnell sein.

Viel interessanter ist, wie die Clients auf den TS connecten:

In unserem Fall waren es Citrix Clients, und da fangen die Probleme (kb955692) an. Lässt sich zwar mit dem verlinkten Patch beheben, ist aber dennoch sehr mühsam. Gerade auch im Zusammenhang mit den Berechtigungen.

Weiter können die RDP Tools bei WPF nicht mehr so einfach optimieren, wie das bei nativen Windows Forms Anwendungen möglich ist.

Alles in allem funktioniert es. Wegen der Performance würde ich einen Prototypen empfehlen - aber Anwendungen über einen TS sind ja nie wirklich berauschend schnell.

Thema: MVVM : Öffnen einer Seite durch Model
Am im Forum: GUI: WPF und XAML

Hi,

Zitat
das ganze muss doch aber auch ohne MEF MAF oder einen IOC Container möglich sein oder ?
Ja das ist es allemal. Der Vorteil dieser Abstraktion ist, dass du als Fenster-Backend nutzen kannst was du willst: Du kannst direkt die WPF Fenster nutzen, du kannst aber auch einen Dockingmanager - an der Stelle führe ich mal AvalonDock auf - oder irgend eine Eigenkreation nutzen. Das ganze wird flexibler, und der Abstraktionsaufwand hällt sich in überschaubaren Grenzen.

Wegen dem Tree-View:
Wieso erfindest du das Rad neu? Google einfach nach TreeView + MVMV und schon kriegst du Beispielimplementationen. Das hier schaut ganz brauchbar aus: Simplifying the WPF TreeView by Using the ViewModel Pattern
Damit hast du eine saubere Implementation als Grundlage, und du kannst das auf dein Problem 1:1 übertragen.

Bleib mir mit Winforms bloss auf Distanz :D

Thema: MVVM : Öffnen einer Seite durch Model
Am im Forum: GUI: WPF und XAML

Nope:

Deine Model Klassen sind mit den Viewmodelklassen stark gebunden, ein Viewmodel ist ein Wrapper um ein (oder mehrere) Model Klassen.

Ein Viewmodel hingegen ist NICHT stark an eine View gebunden, sondern nur lose über Properties welche das VM bereitstellt, und die View dann über Databinding losen Zugriff hat.

Folgendes wäre eine Methode in einem ViewModel, welches MVMV schön demonstriert:


void ShowCustomerDetail(Customer cust){
	
	var vm = new CustomerViewModel(cust);
	var workbenchServ = ServiceLocator.Resolve<IWorkbenchService>();
	workbenchServ.Show(vm);
}

Was dir hier auffallen sollte ist, dass ein VM "gezeigt wird". Mit welcher View ein VM gezeigt wird, abstrahiere -zumindest ich - immer mit einem WorkbenchService. Man hat daher beim Appstart oft Mappings, wo die ViewModel-Klassen zu Views gemappt werden.

Ein Auszug aus meinem Code:


/// <summary>
        /// Configure Services
        /// </summary>
        void ConfigureServices() {

            // config the ViewModel to View mappings for Dialoges  / WorkbenchServices
            var mappingService = _serviceLocator.Resolve<IWorkBenchService>().MappingService;
            mappingService.RegisterMapping(typeof(AboutViewModel), typeof(AboutControlView));
            mappingService.RegisterMapping(typeof(AllPluginsViewModel), typeof(PluginOverviewControl));

            mappingService.RegisterMapping(typeof(SalesmanMapViewModel), typeof(SalesmanMapView));
            mappingService.RegisterMapping(typeof(AllCustomersViewModel), typeof(AllCustomersView));
            mappingService.RegisterMapping(typeof(CustomerViewModel), typeof(CustomerView));


            mappingService.RegisterMapping(typeof(DocumentViewerViewModel), typeof(DocumentViewerView));
       // usw...
}

Für einzelne Items in einem Fenster nutzt man dann kein Mapping mehr sondern DataTemplates, die je nach ViewModel-Typ gewählt werden.

Thema: Redundantes Xaml
Am im Forum: GUI: WPF und XAML

Deine fast gleichen Datatemplates unterscheiden sich ja im Image - wenn du z.B. aus der hardcodierten Source ein ...

<Image  Width="16" Height="16" Source="{Binding MyImage}" />
... machst sind die DataTemplates identisch und du kannst das einmal definieren und zweimal referenzieren.

Ich sehe in dem Falle aber kein grossen Problem von redundantem XAML. XAML ist in vielen belangen redundanter als Code...

Thema: Aus dynamisch geladenem Flowdocument ein XpsDocument generieren
Am im Forum: GUI: WPF und XAML

Ich habe nun als Notlösung das dynamisch geladene Flowdocument einem Fenster als Child zugewiesen. Sobald das geschehen ist, ziehen die Databindings und das Flowdocument hat seinen Inhalt.

So klappt es mit dem Databinding, nur ist das natürlich relativ umständlich, wenn man ohne Vorschau drucken will, oder mehrere Flowdocuments mit einem Paginator weiter bearbeiten will.

Ich bin in meinen Recherchen über einige Blogs/Beiträge gestolpert, die genau das Problem auch angehen, aber es scheint nicht wirklich eine zuverlässige Methode zu geben.


            private static void FlushDispatcher(Dispatcher ctx, DispatcherPriority priority) {
                ctx.Invoke(priority, new DispatcherOperationCallback(delegate { return null; }), null);
            }
Dieser Hack wird mit dem CurrentDispatcher aufgerufen, und lässt gewisse Databindings ausführen - in meinem konkreten Fall hat das aber auch nichts gebracht, da das Element weiterhin nicht den "IsLoaded" Status bekommt.
Quelle



Falls jemand meinen Monolog hier etwas bereichern will - nur zu

Thema: Dynamisch erstellten Button ein Clickereignis hinzufügen
Am im Forum: GUI: Windows-Forms

Hi herbivore,

Dass man sowas mit Delegates lösen sollte ist klar. u.U. ich würde sogar noch weiter gehen und solche User-Aktionen in Commands kapseln.

Mich hat lediglich interessiert dies so zu lösen wie sich der Threadersteller das vorgestellt hatte. Es ist bestimmt Quick & Dirty aber dafür auch ziemlich dynamisch. Es ist aber bestimmt auch nicht eine saubere Lösung, da gebe ich dir vollauf recht.

Wie dem auch sei, wir kennen die Umstände ja nicht. Wenn das Ganze hier z.B. als Ziel hat, Shortcuts von Commands auf verschiedenen Tab-Pages auf die Front-Seite zu legen, benötigt das noch weitere Behandlung - z.B. um keine doppelten Shortcuts anzulegen. Spätestens dann kommt man nicht um eine gescheite Verwaltung der Commands herum.


Mit clone meine ich eigentlich kopieren - das erstellen eines Events mit den gleichen Eigenschaften.
~ Delegate.Clone Method (System)

Thema: Dynamisch erstellten Button ein Clickereignis hinzufügen
Am im Forum: GUI: Windows-Forms

Kann man nicht die Delegates aus dem Eventhandler mittels Reflection auslesen, und damit dann einen Clone des Events machen?

So nach dem Prinzip hier: http://www.bobpowell.net/eventsubscribers.htm

Schöner wäre es aber definitiv wenn du eine Liste/Dictionary mit Delegates für deine Commands definierst und darin den Lookup machst, welcher Button welchen Command ausführen soll.

Thema: Aus dynamisch geladenem Flowdocument ein XpsDocument generieren
Am im Forum: GUI: WPF und XAML

Hallo,

Ich habe in Flowdocuments, die von xaml Files dynamisch geladen werden, meine Rapport-Layouts definiert.
Bei statischen Inhalten funktioniert das problemlos. Mein Problem liegt nun darin, dass ich in den Flowdocuments Databindings habe, die den Inhalt dynamisch erzeugen.

Flowdocuments unterstützen Databinding von sich aus nicht wirklich, daher folge ich dem Weg den Vincent Van Den Berghe in einem interessanten Artikel (Create Flexible UIs with Flow Documents And Data Binding) beschrieben hat, und ich habe das ganze so adaptiert.

Ein Beispiel eines solchen xamls:


    <FlowDocument 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:flowdoc="clr-namespace:Archimedes.Patterns.WPF.FlowDocuments;assembly=Archimedes.Patterns.WPF"
              PageHeight="29.7cm" PageWidth="21cm" ColumnWidth="21cm">

        <Paragraph>
            <Bold>Mein schöner Rapport</Bold>
        </Paragraph>


        <flowdoc:ItemsContent ItemsSource="{Binding AllCustomers}" >
            <flowdoc:ItemsContent.ItemsPanel>
                <DataTemplate>
                    <flowdoc:Fragment>
                        <Table BorderThickness="1" BorderBrush="Black">
                            <TableRowGroup flowdoc:Attached.IsItemsHost="True">
                                <TableRow Background="LightBlue">
                                    <TableCell>
                                        <Paragraph>Customer</Paragraph>
                                    </TableCell>
                                    <TableCell>
                                        <Paragraph>Last visit</Paragraph>
                                    </TableCell>
                                </TableRow>
                            </TableRowGroup>
                        </Table>
                    </flowdoc:Fragment>
                </DataTemplate>

            </flowdoc:ItemsContent.ItemsPanel>
            <flowdoc:ItemsContent.ItemTemplate>
                <DataTemplate>
                    <flowdoc:Fragment>
                        <TableRow>
                            <TableCell>
                                <Paragraph>
                                    <flowdoc:BindableRun BoundText="{Binding MatchCode}" />
                                </Paragraph>
                            </TableCell>
                            <TableCell>
                                <Paragraph>
                                    <flowdoc:BindableRun BoundText="{Binding LastSalesmanVisit}"/>
                                </Paragraph>
                            </TableCell>
                        </TableRow>
                    </flowdoc:Fragment>
                </DataTemplate>
            </flowdoc:ItemsContent.ItemTemplate>
        </flowdoc:ItemsContent>

    </FlowDocument>
Zu beachten ist, das die interessante Klasse flowdoc:ItemsContent 1:1 der aus dem oben verlinkten Artikel entspricht.



Das Problem an der Sache ist nun folgendes:
Um die dynamischen Inhalte zu erzeugen muss das Flowdocument nun irgendwie geladen und als Visual gerendert werden. Will ich es dem User als Vorschau darstellen funktioniert das also problemlos. (Dynamisch laden, DataContext setzten, als Child eines Window/Controls ) setzten und das ganze funktioniert.

Was ich aber möchte ist, aus dem FlowDocument z.B. ein XpsDocument generieren, welches ich dann wahlweise dem Nutzer anzeigen aber eben auch direkt drucken kann.

Ich habe folgenden Code geschrieben (mehr zusammengeklaut), um aus den FlowDocument ein XpsDocument zu erzeugen:


        /// <summary>
        /// Helper method to create page header or footer from flow document template
        /// </summary>
        /// <param name="data">report data</param>
        /// <returns></returns>
        public static XpsDocument CreateXpsDocument(FlowDocument document) {
            MemoryStream ms = new MemoryStream();
            Package pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
            string pack = "pack://report.xps";
            PackageStore.RemovePackage(new Uri(pack));
            PackageStore.AddPackage(new Uri(pack), pkg);
            XpsDocument xpsdoc = new XpsDocument(pkg, CompressionOption.NotCompressed, pack);
            XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(xpsdoc), false);

            DocumentPaginator dp = 
                ((IDocumentPaginatorSource)document).DocumentPaginator;
            rsm.SaveAsXaml(dp);
            return xpsdoc;
        }
Das liefert mir aber bei den dynamischen Inhalten nichts zurück, weil das Flowdocument nie als VisualChild eines Controls definiert wird, und somit auch nie das Databinding zum Zuge kommt.

Jemand eine Idee wie man das elegant löst, oder einen einfacheren Weg um Flowdocuments mit Databinding dynamisch zu laden um daraus ein Rapport-Dokument zu erstellen?

Grüsse
IsNull



Cross-Post Hinweis:
Ich habe im Vorfeld eine sehr ähnliche (die Frage konnte ich nun weiter konkretisieren) Anfrage hier gestellt aber noch keine Antwort erhalten.