3

J'ai une condition de concurrence moche avec un WPerc usercontrol, qui est une sorte de ComboBox étendu: Le UserControl définit principalement deux DependencyProperties, l'un est l'élément sélectionné, l'autre est une liste , à partir de laquelle l'élément sélectionné peut être choisi. Les deux sont liables, de sorte que le contrôle peut être initialisé avec ou sans un élément sélectionné et les deux propriétés peuvent être modifiées via une liaison (modification DataContext), la sélection peut en outre changer en raison de l'interaction de l'utilisateur. Le contrôle UserControl contient une zone de liste déroulante, dont ItemsSource et SelectedItem sont synchronisés avec ma propriété de liste et SelectedItem du contrôle UserControl - jusqu'ici tout va bien. Le problème est maintenant que si les deux propriétés sont modifiées (quasi simultanément) de l'extérieur lors de la définition d'un nouveau DataContext avec les deux valeurs, il arrive que SelectedItem soit correctement défini mais la mise à jour de la liste entraîne la réinitialisation la valeur précédemment définie -> corruption de mon DataContext. Pour faire court: je dois trouver un moyen de "verrouiller" mon SelectedItem pendant la mise à jour de la liste - mais observer simplement les PropertyChanged-Events ne suffit pas, car je les reçois APRÈS les mises à jour, où l'état à retenir est déjà perdu. Plus loin je ne peux pas identifier, si le changement de sélection a été provoqué par l'utilisateur ou par (correctement) la liaison ou (indirectement désiré) par l'autre liaison ... Je pense que j'aurais besoin de certains événement BeforePropertyChanged ou OnPropertyChanging pour mes DependencyProperties - ou une autre façon de gérer l'ordre des mises à jour simultanées des deux propriétés.Synchroniser les liaisons de plusieurs propriétés dans un UserControl

Toute suggestion bienvenue :)

Notez que je parle d'une liste pour sélectionner un élément de, mais en réalité il est une structure plus complexe qui permet un tri rapide et le filtrage, qui est aussi la raison pour laquelle je ne utilisez un ItemsControl ici, mais je ne pense pas que ce soit pertinent pour la question.

+0

Avez-vous réussi à résoudre ce problème?J'ai un problème similaire que je suis en train de creuser .. –

+0

Aucune réponse pour l'instant, comme vous pouvez le voir. Ce que j'ai déjà fait, assurez-vous que les liaisons sont toujours utilisées dans le bon ordre (en XAML), d'abord le ItemsSource, puis le SelectedItem. Mais cela ne semble pas assez robuste, surtout si vous réutilisez le contrôle pour changer DataContexts. –

+0

Un ajout: j'avais expérimenté avec "IsAsync" pour mes liaisons de source-articles. Maintenant que je les ai tous placés à IsAsync = False, cela semble garantir le bon ordre pour * mon * cas. Néanmoins, je pense qu'il serait intéressant d'apprendre d'autres techniques de synchronisation, car il peut y avoir des scénarios plus complexes dans lesquels vous en avez toujours besoin. –

Répondre

1

Cela ne peut pas aider la situation, et n'est probablement pas la bonne façon de le faire, mais vous avez parlé d'un événement OnPropertyChanging pour vos propriétés de dépendance.

Il se trouve que lorsque vous créez des propriétés de dépendance, vous pouvez spécifier un rappel dans le PropertyMetadata qui se déclenche lorsque la propriété change, qui contient à la fois l'ancienne et la nouvelle valeur dans EventArgument.

Voici un exemple d'une propriété de texte avec un rappel

public static DependencyProperty TextProperty = DependencyProperty.Register 
               ("Text", typeof(string), 
               typeof(DecimalTextBox), 
               new PropertyMetadata("", OnTextPropertyChanged)); 

Le dernier paramètre est celui que vous recherchez. Le premier paramètre du constructeur PropertyMetadata est une valeur par défaut pour la propriété. Le second est l'endroit où vous enregistrez un callback propertychanged qui se produit lorsque la propriété change. Dans ce rappel, vous pouvez gérer les liaisons pour vous assurer de ne pas écraser l'élément SelectedItem de votre datacontext.

private static void OnTextPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 

     var box = ((TextBox)sender); 

     if (((string)e.NewValue)==badvalue) 
       box.Text= e.OldValue); 


    } 

Pour être honnête, je ne sais pas comment cela vous aide à votre situation, comme je sais toujours pas comment vérifier si la valeur NULL est valide ou non. (Ce que je pourrais faire est de ne pas autoriser les valeurs nulles s'il y a une ItemsSource à moins que les itemssource ne changent juste [et j'utiliserais un type d'indicateur dans le callback modifié ItemsSource qui se réinitialise une fois que l'item selected est changé]). Je ne suis pas très confiant sur l'async, mais vous pourriez peut-être mettre un verrou ici.

u_u

+0

En attendant, je l'ai résolu différemment, mais en utilisant le coercevaluecallback pourrait m'aider et correspond à ce que je demandais, de sorte qu'il répond à ma question. Je vous remercie. –

+0

Comment avez-vous résolu le problème différemment? S'il vous plaît ajouter la réponse que vous avez utilisé ne pas marquer celui-ci comme le bon. –

Questions connexes