2009-12-03 11 views
23

Ich verwende WPF mit dem Model-View-ViewModel-Muster. Daher sind meine Code-hinter-Dateien (.xaml.cs) alle leer, außer für den Konstruktor mit einem Aufruf von InitializeComponent. Daher habe ich für jede .xaml-Datei eine passende, unbrauchbare .xaml.cs-Datei.XAML ohne den Code .xaml.cs hinter Dateien

Ich schwöre ich irgendwo gelesen, dass, wenn der Code hinter der Datei leer ist, mit Ausnahme des Konstruktors, gibt es eine Möglichkeit, die Datei aus dem Projekt insgesamt zu löschen. Nach der Suche im Netz, so scheint es, dass der geeignete Weg, dies zu tun, ist das ‚x: Subclass‘ verwenden Attribut:

<UserControl 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" 
    xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit" 
    x:Class="MyNamespace.MyClass" 
    x:Subclass="UserControl" 
    d:DesignWidth="700" d:DesignHeight="500"> 

Dies führt folgende Aktionen in der generierten .g.cs Datei:

  1. Entfernt den partiellen Klassenmodifikator in MyClass.
  2. Fügt der Unterklassenliste die Klasse 'UserControl' hinzu.

Scheint perfekt. In der Tat, wenn Sie die .xaml.cs-Datei im Build noch haben, kompiliert es nicht mehr wegen des fehlenden Partials - also denke ich, dass das korrekt sein muss. Wenn ich jedoch die überflüssige Datei aus dem Build entfernen und ausführen, wird das Steuerelement nicht korrekt initialisiert (es ist leer). Dies ist vermutlich, weil InitializeComponent() nicht aufgerufen wird. Ich sehe, dass InitializeComponent nicht virtuell ist, daher scheint es, dass es für die Basisklasse keine Möglichkeit gibt, sie aufzurufen (ohne Reflektion zu verwenden).

Fehle ich etwas?

Danke!

Eric

Antwort

13

Wenn Sie folgen Josh Smith's MVVM article, verwendet er für Datatemplates Ansichten anstatt Bedienelemente. Wenn Sie Ihre DataTemplates in ResourceDictionaries einfügen, haben sie überhaupt keinen Code-Behind. Wenn Sie den Code-Behind Ihres Benutzersteuerelements nicht verwenden, bedeutet das nicht, dass Sie einen DataTemplate-Ansatz verwenden könnten?Wenn Sie das tun, wird WPF dafür sorgen, dass Ihre View für Sie mit Ihrem ViewModel verbunden wird.

+0

Danke Scott. Dies ist definitiv ein besserer Ansatz. – Eric

+0

+1 Ich benutze auch diesen Weg. Es funktioniert so großartig, es ist fast wie Magie. –

+1

Hinweis: ist in WPF verfügbar, aber nicht in Silverlight. – MrSharps

2

hatte ich ein Gespräch mit einem Windows-Client-Teammitglied bei PDC darüber, und gerade jetzt, mir wurde gesagt, dass es keine offiziell unterstützter Weg ist, um vollständig den Code hinter Datei zu beseitigen. Wie Sie sehen können, können Sie es kompilieren, aber InitializeComponent() wird nie aufgerufen, so dass das Steuerelement nicht ordnungsgemäß eingerichtet wird.

Die x:Subclass attribute "Verwendung ist in erster Linie für Sprachen gedacht, die partielle Klassendeklarationen nicht unterstützen." Es war nicht beabsichtigt, dieses Verhalten (leider) zuzulassen.

31

Als weitere Option, wenn Sie mit Datatemplates den ganzen Weg nicht gehen wollen, hier ist ein alternativer Ansatz für Benutzersteuerelemente:

Verwenden Sie das x: Code-Attribut den Konstruktor-Aufruf in der XAML einzubetten:

<x:Code><![CDATA[ public MyClass() { InitializeComponent(); }]]></x:Code> 

Eric

+2

diskutiert, die eine sehr glatte Lösung ist. –

+0

süß. wer hätte das gedacht? –

+3

naja ... Ich habe das aufgefrischt, weil es sehr clever ist, aber es gibt etwas, das sich einfach nicht richtig anfühlt, wenn man einen solchen CDATA-Code in seinen XAML-Dateien hat ... Wie auch immer jemand in einem ähnlichen Thema gefragt hat Möchten Sie die leeren Code-Behind-Dateien entfernen? sie sind nicht störend, man kann sie kaum dort sitzen sehen. Dennoch mag ich deine Kreativität :-) –

0

aus purer Neugier, haben Sie versucht, dies mit:

x:Subclass="Control" 

Standardmäßig erfordern Benutzersteuerelemente den Aufruf InitializeComponent(), defacto-standardmäßige Steuerelemente jedoch nicht. Es würde mich interessieren, ob das funktioniert.

-Doug

+0

Habe das gerade versucht. Es hat das Verhalten nicht verändert. Ohne den Aufruf von InitializeComponent() ist das Steuerelement leer. – Eric