Freitag, 29. Oktober 2010

Ungültige oder nicht wohlgeformte Anwendung. Überprüfen Sie das Manifest.

Vielleicht ist der ein oder andere schon mal über den Silverlight Fehler

Ungültige oder nicht wohlgeformte Anwendung. Überprüfen Sie das Manifest.
oder in englisch
Invalid or malformed application: Check manifest.
gestolpert.

 
Im Netz gibt es lange Threads mit verschiedenen Lösungen für das Problem. Hier die Lösungen die mir kürzlich geholfen hat:

 
  • Wir haben in unseren SL-Projekten den Namespace der App.xaml.cs geändert, und die Änderung freilich auch in der App.xaml im x:Class Attribut nachgezogen. Vergessen hatten wir in den Eigenschaften des Silverlight Projekts auf der Seite "Silverlight" unter "Startup Object" auch das "neue" App-Objekt eingetragen. Daher der Fehler. Bei korrekter Einstellung geht alles wieder.
  • Nach der Fehlermeldung "Xap packaing failed: OutOfMemoryException" kommt der Fehler auch. In diesem Fall wählt man im Studio nicht "Rebuild Solution" (was ich normalerweise tue) sondern "Build Solution" - sobald man erfolgreich kompilieren konnte ist der Fehler weg.

 
Es gibt noch andere Ursachen für das Problem und dazu natürlich auch andere Lösungen - diese können gerne als Kommentar hinterlassen werden :-)

Dienstag, 5. Oktober 2010

Silverlight: Properties die in einem Style gesetzt werden sind statisch

Ein Sache die eigentlich offensichtlich ist, hat mich heute überraschend getroffen:

Properties die man innerhalb eines Silverlight Custom Control per <setter> setzt, sind statisch und alle Instanzen dieses Controls teilen sich die gleiche Instanz für den Property-Inhalt.

Nach kurzem suchen in der MSDN wurde deutlich dass das auch das erwartete Verhalten ist:

"Contains property setters that can be shared between instances of a type." [1]

Folgendes Szenario:
Ich wollte ein ContontControl schreiben, das ein Control enthält und eine IsDirty-Property bereitstellt. Wird IsDirty auf true gesetzt, soll sich das enthaltene Control entsprechend ändern, z.B. indem der Text jetzt in rot dargestellt wird. Es sollte die Möglichkeit bestehen dass eine TextBox im Dirty-State anders aussieht als z.B. eine Textbox.
Zu diesem Zewck habe ich eine kleine ResourceSelector Komponente geschrieben, die aufgrund des Typnamens des enthaltenen Controls ein Storyboard auswählt und dieses auf das enthaltene Control anwendet. Auf diese Weise kann man für jedes Control einen eigenen Dirty-Style definieren.
Meinem DirtyContainer-Control habe ich dann eine Property StoryboardSelector spendiert, die eine Instanz von meinem ResourceSelector aufnehmen kann.

Das führt zu folgendem Markup:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
  xmlns:Local="clr-namespace:Silverlight.Controls"
  >

  <Style TargetType="Local:DirtyContainer">
    
    <Setter Property="StoryboardSelector">
      <Setter.Value>
        <Local:ResourceSelector>
          <Local:ResourceSelector.Resources>
            <ResourceDictionary>
              <Storyboard x:Key="TextBox" >
                ...
              </Storyboard>

              <Storyboard x:Key="ComboBox">
                ...
              </Storyboard>

              <Storyboard x:Key="CheckBox">
                ...
              </Storyboard>
            </ResourceDictionary>
          </Local:ResourceSelector.Resources>
        </Local:ResourceSelector>
      </Setter.Value>
    </Setter>
    
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Local:DirtyContainer">
          <Grid>
            <ContentControl x:Name="Content" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"
                HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
                                            Padding="1">

            </ContentControl>
          </Grid>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

Wenn sich nun die IsDirty-Eigenschaft von meinem DirtyContainer ändert, suche ich in dem StoryboardSelector nach einem passenden Storyboard basierend auf dem Typnamen (m_Content ist die Instanz des ContentControls aus dem Template):

StoryboardSelector.ResourceSwitch = m_Content.Content.GetType().Name;
DirtyStoryboard = StoryboardSelector.CurrentResource as Storyboard;

Storyboard.SetTarget(DirtyStoryboard, m_Content.Content as DependencyObject);
DirtyStoryboard.Begin();

Geknallt hat es dann in Zeile 3, wenn man zweimal eine Combobox in der Applikation verändert hat:


Der Vorgang ist auf einer aktiven Animation oder einem aktiven Storyboard nicht gültig.
Das Stammstoryboard muss zunächst angehalten werden.


Diese Fehlermeldung ist dem Umstand geschuldet, dass jetzt alle Comboboxen das gleiche Storyboard verwenden, aber eine Storyboard-Instanz immer nur ein Target haben darf.

So weit, so gut, das verstehe ich alles. Aber ich suche eine Lösung bei der ich bereits im Control-Style einen Standard für die Storyboards setzen kann. Derzeit habe ich den ganzen ResourceSelector in die Resources-Auflistung des ContentControls geschoben und hole mir die Instanz im OnApplyTemplate:

StoryboardSelector = m_Content.Resources["ResourceSelector"] as ResourceSelector;



Keine wirklich tolle Lösung - für bessere Ideen bin ich jederzeit offen...