2017-07-07 4 views
-1

J'ai un fichier qui contient des types de données primitifs tels que short et uint et float dans leur forme de données natives. Je parser le fichier dans une classe, quelque chose comme ça, de sorte que la validité tout est indépendamment suivi et maintenu dans une propriété:Intercepter chaque liaison de données pour exécuter la fonction avec paramètre étroit

// Every class inherits this and therefore has the property "Valid" 
public class Object { public bool Valid {get;set;} } 

// Primitive data types as classes 
public class Short : Object { public short Value {get;set;} } 
public class UInt : Object { public uint Value {get;set;} } 
public class Float : Object { public float Value {get;set;} } 
// ... and other data types as classes 

groupes plus importants de ces classes primitives sont utilisées, mais sont étrangères à ce question. Finalement, je reçois par des biens contenus à la plus grande portée, ce qui représente le fichier lui-même:

public class File : Object { public byte[] Data {get;private set;} } 
public class FileTypeA : File { public Float X {get;set;} } 

J'utilise la liaison de données et XAML avec Windows Presentation Foundation. Je montre un exemple trop simplifié ici, mais il suffit de dire que la liaison de données fonctionne comme prévu en utilisant un tas de choses INotifyPropertyChanged.

J'ai un CRC32 des données du fichier stockées dans un objet contenu, quelque chose comme ceci:

// This class contains private methods for calculating the CRC32 using a byte[] parameter 
public class CRC32 : UInt { } 

// The file's header data stores a CRC32 of the file data (excluding the header) 
public class Header : Object { public CRC32 CRC {get;set;} } 

// The aforementioned FileTypeA class is really more along the lines of this: 
public class FileTypeA : File { public Header H {get;set;} public Float X {get;set;} } 

Lorsque l'utilisateur ouvre un fichier de type FileTypeA, j'instancier un objet FileTypeA et qui a la réaction en chaîne de l'analyse syntaxique de manière efficace toutes les données de fichier, quelque chose comme ceci:

// OpenFileDialog results in a string of the file path, for example: 
string filepath = @"path\to\tests\test.a"; 

// Obtain byte[] of file data and store it along with the filepath in the FileTypeA object 
FileTypeA fta = new FileTypeA(System.IO.File.ReadAllBytes(filepath), filepath); 

// Instantiate and show a window suitable for displaying the data of type FileTypeA. 
// The window stores a property of type FileTypeA. 
FTAWindow fta_window = new FTAWindow(fta); 
fta_window.Show(); 

FTAWindow contient une seule propriété que j'utilise pour référencer toutes les données FileTypeA:

public class FTAWindow : Window { public FileTypeA A {get;set;} } 

J'utilise la liaison de données pour afficher et prévoir la modification des différentes propriétés au sein A, notamment les propriétés appelées Value dans les objets de type primitif contenus. Par exemple, dans le XAML, je fais quelque chose comme:

<TextBox 
    x:Name="X_TextBox_Value" 
    Foreground="{Binding Path=A.X.Valid, Converter={StaticResource ValidToColor}}" 
    Text="{Binding Path=A.X.Value}" 
/> 

je montre aussi la valeur CRC32 dans la fenêtre.

Le problème est le suivant: Je souhaite recalculer dynamiquement le CRC32 des données de fichier lorsque l'utilisateur modifie les données du fichier via la liaison de données dans la fenêtre. La liaison de données passe directement des contrôles utilisateur dans la fenêtre aux propriétés; mais j'ai besoin de passer la fonction de calcul CRC32 A.Data alors que les propriétés liées aux données ont toutes une portée spécifique, non apparentée et plus étroite comme A.X.Value et les propriétés construites ne peuvent pas accéder aux valeurs des propriétés construites adjacentes de leur classe contenue. Existe-t-il un moyen d'intercepter chaque liaison de données (ou enregistrer des notifications à tous les changements, peut-être à travers une classe de centre de notification improvisée comme AppKit d'Apple) sans utiliser IValueConverter pour que je puisse appeler une fonction de calcul CRC de FTAWindow qui aura accès à A? À la portée de la propriété liée, il n'y a pas d'accès à A. Je ne pense pas que je suis supposé passer en quelque sorte A dans le xaml aux setters des propriétés liées.

Je veux avoir toutes les données de liaison setter de A propriété de la fenêtre (comme la mise en A.X.Value) faire ce qu'il fait normalement (définir la valeur), puis d'exécuter cette fonction située dans le code-behind de la fenêtre:

private void RecalculateCRC() 
{ 
    A.H.CRC.Value = CRC32.Calculate(A.Data); 
} 

Comment est-ce que je fais ceci?Comment puis-je appeler une méthode de fenêtre (RecalculateCRC()) avec le paramètre (A.Data) chaque fois que la propriété de la fenêtre est définie à l'aide de la liaison de données?

Est-ce aussi simple que "How do I call a function via xaml?" Si oui, alors comment puis-je appeler la fonction après la résolution de la liaison de données? Dois-je utiliser un déclencheur de style, par exemple avec l'événement LostFocus d'un TextBox? Toujours en rapport avec: Calling functions with parameters in xaml


MISE À JOUR:

Je cela pour la INotifyPropertyChanged:

public event PropertyChangedEventHandler PropertyChanged; 
public void NotifyPropertyChanged(string propName) 
{ 
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); 
    // I can put something here... 
} 

je pourrais lier A à la fenêtre elle-même et l'utiliser de sorte que lorsque les biens changements, il est appelé. Cela signifierait de lier l'objet fichier lui-même à la fenêtre et d'utiliser un IValueConverter comme analyseur de données, ce qui n'a aucun sens.

Je vois deux options:

  • stocker une référence au fichier ou ses byte[] données en tant que propriété de chaque classe comme Float, mais cela semble être un hack et un gaspillage.
  • N'appelez pas la fonction en utilisant la liaison de données (alors pourquoi utiliser la liaison de données?). Au lieu de cela, utilisez des événements de conclusion (tels que LostFocus avec chaque zone de texte) sur les contrôles utilisateur pour appeler la fonction.

Les déclencheurs de style semblent également être un hack. Je dirais que les événements sont plus proches, mais sont vraiment destinés à être plus loin des tâches de manipulation de données.

Pour l'instant, j'utilise des styles et des événements, c'est assez facile!


connexes:

Subscribe to INotifyPropertyChanged for nested (child) objects

How do I subscribe to PropertyChanged event in my ViewModel?

+0

Désolé, je me suis ennuyé à mi-chemin. Nous n'avons sûrement pas besoin de savoir tout cela pour comprendre votre question. Autant que je sache, cela revient à vouloir faire des calculs chaque fois qu'une valeur de propriété change. Alors, pourquoi ne pas vous abonner à 'INotifyPropertyChanged' comme tout le monde? S'il vous plait prenez le temps de distiller votre question au strict nécessaire, assurez-vous d'inclure un bon mot, expliquez précisément ce que fait ce code, ce que vous voulez faire et ce que vous avez du mal à comprendre. –

+0

@PeterDuniho Dites-moi comment vous abonner à INotifyPropertyChanged dans une réponse. – Sparky

Répondre

0

Abonnez-vous à les changements de propriétés de classe conteneur dans ce que le constructeur de la classe conteneur comme ceci:

public class FileTypeA : File 
{ 
    public Header H {get;set;} 
    public Float X {get;set;} 

    // constructor: 
    public FileTypeA(byte[] givenData, string givenPath) : base(givenData, givenPath) 
    { 
     X = new Float(...); 
     // watch for changes to the property: 
     X.PropertyChanged += MetaChanged; 
    } 

    // gets called when the aforementioned watched properties change: 
    private void MetaChanged(object sender, PropertyChangedEventArgs e) 
    { 
     H.UpdateCRC(Encode(...), ...); 
    } 
} 

Vous pouvez utiliser un fonction commune comme ça, une boucle for avec réflexion pour toutes les propriétés, ou spécifiez manuellement les propriétés.

cela a été utile: https://stackoverflow.com/a/7825054/2846508